Author: rmacklem
Date: Sun Jan  9 02:10:54 2011
New Revision: 217176
URL: http://svn.freebsd.org/changeset/base/217176

Log:
  Modify readdirplus in the experimental NFS server in a
  manner analogous to r216633 for the regular server. This
  change busies the file system so that VFS_VGET() is
  guaranteed to be using the correct mount point even
  during a forced dismount attempt. Since nfsd_fhtovp() is
  not called immediately before readdirplus, the patch is
  actually a clone of pjd@'s nfs_serv.c.4.patch instead of
  the one committed in r216633.
  
  Reviewed by:  kib
  MFC after:    10 days

Modified:
  head/sys/fs/nfsserver/nfs_nfsdport.c

Modified: head/sys/fs/nfsserver/nfs_nfsdport.c
==============================================================================
--- head/sys/fs/nfsserver/nfs_nfsdport.c        Sat Jan  8 23:08:13 2011        
(r217175)
+++ head/sys/fs/nfsserver/nfs_nfsdport.c        Sun Jan  9 02:10:54 2011        
(r217176)
@@ -1685,6 +1685,7 @@ nfsrvd_readdirplus(struct nfsrv_descript
        struct iovec iv;
        struct componentname cn;
        int not_zfs;
+       struct mount *mp;
 
        if (nd->nd_repstat) {
                nfsrv_postopattr(nd, getret, &at);
@@ -1854,7 +1855,24 @@ again:
                toff = off;
                goto again;
        }
+
+       /*
+        * Busy the file system so that the mount point won't go away
+        * and, as such, VFS_VGET() can be used safely.
+        */
+       mp = vp->v_mount;
+       vfs_ref(mp);
        VOP_UNLOCK(vp, 0);
+       nd->nd_repstat = vfs_busy(mp, 0);
+       vfs_rel(mp);
+       if (nd->nd_repstat != 0) {
+               vrele(vp);
+               free(cookies, M_TEMP);
+               free(rbuf, M_TEMP);
+               if (nd->nd_flag & ND_NFSV3)
+                       nfsrv_postopattr(nd, getret, &at);
+               return (0);
+       }
 
        /*
         * Save this position, in case there is an error before one entry
@@ -1914,9 +1932,8 @@ again:
                                            vp, dp->d_fileno);
                                if (refp == NULL) {
                                        if (usevget)
-                                               r = VFS_VGET(vp->v_mount,
-                                                   dp->d_fileno, LK_SHARED,
-                                                   &nvp);
+                                               r = VFS_VGET(mp, dp->d_fileno,
+                                                   LK_SHARED, &nvp);
                                        else
                                                r = EOPNOTSUPP;
                                        if (r == EOPNOTSUPP) {
@@ -2035,6 +2052,7 @@ again:
                ncookies--;
        }
        vrele(vp);
+       vfs_unbusy(mp);
 
        /*
         * If dirlen > cnt, we must strip off the last entry. If that
_______________________________________________
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