Author: pjd
Date: Tue Dec 21 23:15:40 2010
New Revision: 216633
URL: http://svn.freebsd.org/changeset/base/216633

Log:
  Use newly added NFSRV_FLAG_BUSY flag for nfsrv_fhtovp() to keep mount point
  busy. This fixes a race where we can pass invalid mount point to VFS_VGET()
  via vp->v_mount when exported file system was forcibly unmounted between
  nfsrv_fhtovp() and VFS_VGET().
  
  Reviewed by:  kib
  MFC after:    5 days

Modified:
  head/sys/nfsserver/nfs_serv.c

Modified: head/sys/nfsserver/nfs_serv.c
==============================================================================
--- head/sys/nfsserver/nfs_serv.c       Tue Dec 21 23:12:45 2010        
(r216632)
+++ head/sys/nfsserver/nfs_serv.c       Tue Dec 21 23:15:40 2010        
(r216633)
@@ -3036,9 +3036,11 @@ nfsrv_readdirplus(struct nfsrv_descript 
        int v3 = (nfsd->nd_flag & ND_NFSV3);
        int usevget = 1, vfslocked;
        struct componentname cn;
+       struct mount *mntp = NULL;
 
        nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
        vfslocked = 0;
+       vp_locked = 0;
        if (!v3)
                panic("nfsrv_readdirplus: v3 proc called on a v2 connection");
        fhp = &nfh.fh_generic;
@@ -3058,14 +3060,17 @@ nfsrv_readdirplus(struct nfsrv_descript 
        if (siz > xfer)
                siz = xfer;
        fullsiz = siz;
-       error = nfsrv_fhtovp(fhp, 0, &vp, &vfslocked, nfsd, slp,
-           nam, &rdonly, TRUE);
-       vp_locked = 1;
-       if (!error && vp->v_type != VDIR) {
-               error = ENOTDIR;
-               vput(vp);
-               vp = NULL;
-               vp_locked = 0;
+       error = nfsrv_fhtovp(fhp, NFSRV_FLAG_BUSY, &vp, &vfslocked, nfsd, slp,
+           nam, &rdonly);
+       if (!error) {
+               vp_locked = 1;
+               mntp = vp->v_mount;
+               if (vp->v_type != VDIR) {
+                       error = ENOTDIR;
+                       vput(vp);
+                       vp = NULL;
+                       vp_locked = 0;
+               }
        }
        if (error) {
                nfsm_reply(NFSX_UNSIGNED);
@@ -3207,8 +3212,8 @@ again:
                                 * For readdir_and_lookup get the vnode using
                                 * the file number.
                                 */
-                               error = VFS_VGET(vp->v_mount, dp->d_fileno,
-                                   LK_SHARED, &nvp);
+                               error = VFS_VGET(mntp, dp->d_fileno, LK_SHARED,
+                                   &nvp);
                                if (error != 0 && error != EOPNOTSUPP) {
                                        error = 0;
                                        goto invalid;
_______________________________________________
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