diff options
| author | Paul Saab <ps@FreeBSD.org> | 2004-12-01 06:51:07 +0000 |
|---|---|---|
| committer | Paul Saab <ps@FreeBSD.org> | 2004-12-01 06:51:07 +0000 |
| commit | cd1512508475c5b48e037ffb54fd9339a9cecbec (patch) | |
| tree | b5f91d4db0f16d3dcd4c6380310895ec555d8828 /sys | |
| parent | 3e9c9e432a809378330f7b98e2053c6c7ad8c826 (diff) | |
Notes
Diffstat (limited to 'sys')
| -rw-r--r-- | sys/nfsclient/nfs_vnops.c | 28 |
1 files changed, 28 insertions, 0 deletions
diff --git a/sys/nfsclient/nfs_vnops.c b/sys/nfsclient/nfs_vnops.c index 50edb5886cc0..2d2b7f214bce 100644 --- a/sys/nfsclient/nfs_vnops.c +++ b/sys/nfsclient/nfs_vnops.c @@ -2272,6 +2272,34 @@ nfs_readdirplusrpc(struct vnode *vp, struct uio *uiop, struct ucred *cred) nfsm_adv(NFSX_V3FATTR); tl = nfsm_dissect(u_int32_t *, NFSX_UNSIGNED); doit = fxdr_unsigned(int, *tl); + /* + * Skip loading the attrs for "..". There's a + * race between loading the attrs here and + * lookups that look for the directory currently + * being read (in the parent). We try to acquire + * the exclusive lock on ".." here, owning the + * lock on the directory being read. Lookup will + * hold the lock on ".." and try to acquire the + * lock on the directory being read. + * + * There are other ways of fixing this, one would + * be to do a trylock on the ".." vnode and skip + * loading the attrs on ".." if it happens to be + * locked by another process. But skipping the + * attrload on ".." seems the easiest option. + */ + if (strcmp(dp->d_name, "..") == 0) { + doit = 0; + /* + * We've already skipped over the attrs, + * skip over the filehandle. And store d_type + * as VDIR. + */ + tl = nfsm_dissect(u_int32_t *, NFSX_UNSIGNED); + i = fxdr_unsigned(int, *tl); + nfsm_adv(nfsm_rndup(i)); + dp->d_type = IFTODT(VTTOIF(VDIR)); + } if (doit) { nfsm_getfh(fhp, fhsize, 1); if (NFS_CMPFH(dnp, fhp, fhsize)) { |
