Author: rmacklem
Date: Sun May  1 02:22:54 2011
New Revision: 221290
URL: http://svn.freebsd.org/changeset/base/221290

Log:
  MFC: r220735
  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.

Modified:
  stable/8/sys/fs/nfsclient/nfs_clrpcops.c
Directory Properties:
  stable/8/sys/   (props changed)
  stable/8/sys/amd64/include/xen/   (props changed)
  stable/8/sys/cddl/contrib/opensolaris/   (props changed)
  stable/8/sys/contrib/dev/acpica/   (props changed)
  stable/8/sys/contrib/pf/   (props changed)

Modified: stable/8/sys/fs/nfsclient/nfs_clrpcops.c
==============================================================================
--- stable/8/sys/fs/nfsclient/nfs_clrpcops.c    Sun May  1 01:49:35 2011        
(r221289)
+++ stable/8/sys/fs/nfsclient/nfs_clrpcops.c    Sun May  1 02:22:54 2011        
(r221290)
@@ -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);
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to