svn commit: r220735 - head/sys/fs/nfsclient
Rick Macklem
rmacklem at FreeBSD.org
Sun Apr 17 02:44:52 UTC 2011
Author: rmacklem
Date: Sun Apr 17 02:44:51 2011
New Revision: 220735
URL: http://svn.freebsd.org/changeset/base/220735
Log:
Fix readdirplus in the experimental NFS client so that it
skips over ".." to avoid a LOR race with nfs_lookup(). This
fix is analagous to r138256 in the regular NFS client.
MFC after: 2 weeks
Modified:
head/sys/fs/nfsclient/nfs_clrpcops.c
Modified: head/sys/fs/nfsclient/nfs_clrpcops.c
==============================================================================
--- head/sys/fs/nfsclient/nfs_clrpcops.c Sat Apr 16 23:38:35 2011 (r220734)
+++ head/sys/fs/nfsclient/nfs_clrpcops.c Sun Apr 17 02:44:51 2011 (r220735)
@@ -2942,7 +2942,7 @@ nfsrpc_readdirplus(vnode_t vp, struct ui
nfsquad_t cookie, ncookie;
int error = 0, tlen, more_dirs = 1, blksiz = 0, bigenough = 1;
int attrflag, tryformoredirs = 1, eof = 0, gotmnton = 0;
- int unlocknewvp = 0;
+ int isdotdot = 0, unlocknewvp = 0;
long dotfileid, dotdotfileid = 0, fileno = 0;
char *cp;
nfsattrbit_t attrbits, dattrbits;
@@ -3192,6 +3192,11 @@ nfsrpc_readdirplus(vnode_t vp, struct ui
*cp = '\0';
cp += tlen; /* points to cookie storage */
tl2 = (u_int32_t *)cp;
+ if (len == 2 && cnp->cn_nameptr[0] == '.' &&
+ cnp->cn_nameptr[1] == '.')
+ isdotdot = 1;
+ else
+ isdotdot = 0;
uio_iov_base_add(uiop, (tlen + NFSX_HYPER));
uio_iov_len_add(uiop, -(tlen + NFSX_HYPER));
uio_uio_resid_add(uiop, -(tlen + NFSX_HYPER));
@@ -3269,6 +3274,22 @@ nfsrpc_readdirplus(vnode_t vp, struct ui
unlocknewvp = 0;
FREE((caddr_t)nfhp, M_NFSFH);
np = dnp;
+ } else if (isdotdot != 0) {
+ /*
+ * Skip doing a nfscl_nget() call for "..".
+ * There's a race between acquiring the nfs
+ * node here and lookups that look for the
+ * directory being read (in the parent).
+ * It would try to get a 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.
+ * If the directory is unlocked/relocked,
+ * then there is a LOR with the buflock
+ * vp is relocked.
+ */
+ free(nfhp, M_NFSFH);
} else {
error = nfscl_nget(vnode_mount(vp), vp,
nfhp, cnp, p, &np, NULL, LK_EXCLUSIVE);
More information about the svn-src-head
mailing list