kernel: Properly lock dounmount()
authorFrançois Tigeot <ftigeot@wolfpond.org>
Wed, 6 Feb 2013 08:11:04 +0000 (09:11 +0100)
committerFrançois Tigeot <ftigeot@wolfpond.org>
Sat, 9 Feb 2013 15:24:40 +0000 (16:24 +0100)
* dounmount() wasn't properly locked, make it grab the mntvnode_token

* It is necessary to synchronize against insmntque() clearing the vnode
  linkage

* This commit fixes issue #2506

Thanks to vsrinivas for directions

sys/kern/vfs_syscalls.c

index 53cf1bf..eec6025 100644 (file)
@@ -663,11 +663,12 @@ dounmount(struct mount *mp, int flags)
        int lflags;
        int freeok = 1;
 
+       lwkt_gettoken(&mntvnode_token);
        /*
         * Exclusive access for unmounting purposes
         */
        if ((error = mountlist_interlock(dounmount_interlock, mp)) != 0)
-               return (error);
+               goto out;
 
        /*
         * Allow filesystems to detect that a forced unmount is in progress.
@@ -680,7 +681,7 @@ dounmount(struct mount *mp, int flags)
                mp->mnt_kern_flag &= ~(MNTK_UNMOUNT | MNTK_UNMOUNTF);
                if (mp->mnt_kern_flag & MNTK_MWAIT)
                        wakeup(mp);
-               return (error);
+               goto out;
        }
 
        if (mp->mnt_flag & MNT_EXPUBLIC)
@@ -768,7 +769,7 @@ dounmount(struct mount *mp, int flags)
                lockmgr(&mp->mnt_lock, LK_RELEASE);
                if (mp->mnt_kern_flag & MNTK_MWAIT)
                        wakeup(mp);
-               return (error);
+               goto out;
        }
        /*
         * Clean up any journals still associated with the mount after
@@ -810,7 +811,10 @@ dounmount(struct mount *mp, int flags)
                wakeup(mp);
        if (freeok)
                kfree(mp, M_MOUNT);
-       return (0);
+       error = 0;
+out:
+       lwkt_reltoken(&mntvnode_token);
+       return (error);
 }
 
 static