Author: kib
Date: Wed Jun 22 09:10:52 2016
New Revision: 302079
URL: https://svnweb.freebsd.org/changeset/base/302079

Log:
  MFC r301929:
  Do not assume that we own the use reference on the covered vnode until
  we set MNTK_UNMOUNT flag on the mp.

Modified:
  stable/10/sys/kern/vfs_mount.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/kern/vfs_mount.c
==============================================================================
--- stable/10/sys/kern/vfs_mount.c      Wed Jun 22 09:08:18 2016        
(r302078)
+++ stable/10/sys/kern/vfs_mount.c      Wed Jun 22 09:10:52 2016        
(r302079)
@@ -1222,7 +1222,6 @@ dounmount(struct mount *mp, int flags, s
                VI_LOCK(coveredvp);
                vholdl(coveredvp);
                vn_lock(coveredvp, LK_EXCLUSIVE | LK_INTERLOCK | LK_RETRY);
-               vdrop(coveredvp);
                /*
                 * Check for mp being unmounted while waiting for the
                 * covered vnode lock.
@@ -1230,18 +1229,22 @@ dounmount(struct mount *mp, int flags, s
                if (coveredvp->v_mountedhere != mp ||
                    coveredvp->v_mountedhere->mnt_gen != mnt_gen_r) {
                        VOP_UNLOCK(coveredvp, 0);
+                       vdrop(coveredvp);
                        vfs_rel(mp);
                        return (EBUSY);
                }
        }
+
        /*
         * Only privileged root, or (if MNT_USER is set) the user that did the
         * original mount is permitted to unmount this filesystem.
         */
        error = vfs_suser(mp, td);
        if (error != 0) {
-               if (coveredvp)
+               if (coveredvp != NULL) {
                        VOP_UNLOCK(coveredvp, 0);
+                       vdrop(coveredvp);
+               }
                vfs_rel(mp);
                return (error);
        }
@@ -1251,8 +1254,10 @@ dounmount(struct mount *mp, int flags, s
        if ((mp->mnt_kern_flag & MNTK_UNMOUNT) != 0 ||
            !TAILQ_EMPTY(&mp->mnt_uppers)) {
                MNT_IUNLOCK(mp);
-               if (coveredvp)
+               if (coveredvp != NULL) {
                        VOP_UNLOCK(coveredvp, 0);
+                       vdrop(coveredvp);
+               }
                vn_finished_write(mp);
                return (EBUSY);
        }
@@ -1285,6 +1290,16 @@ dounmount(struct mount *mp, int flags, s
        if (mp->mnt_flag & MNT_EXPUBLIC)
                vfs_setpublicfs(NULL, NULL, NULL);
 
+       /*
+        * From now, we can claim that the use reference on the
+        * coveredvp is ours, and the ref can be released only by
+        * successfull unmount by us, or left for later unmount
+        * attempt.  The previously acquired hold reference is no
+        * longer needed to protect the vnode from reuse.
+        */
+       if (coveredvp != NULL)
+               vdrop(coveredvp);
+
        vfs_msync(mp, MNT_WAIT);
        MNT_ILOCK(mp);
        async_flag = mp->mnt_flag & MNT_ASYNC;
_______________________________________________
svn-src-stable-10@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-stable-10
To unsubscribe, send any mail to "svn-src-stable-10-unsubscr...@freebsd.org"

Reply via email to