summaryrefslogtreecommitdiffstats
path: root/sys/kern/vfs_mount.c
diff options
context:
space:
mode:
authorLuiz Otavio O Souza <luiz@netgate.com>2016-06-30 13:24:42 -0500
committerLuiz Otavio O Souza <luiz@netgate.com>2016-06-30 13:24:42 -0500
commit9d5ffb47ff56597309eb2939cc97b1df4d616797 (patch)
treeb34fd92dce8092bb4cb58c875caabd93e1fece39 /sys/kern/vfs_mount.c
parent1fc6b0207cc2f3cce33817706603caa41a9de24d (diff)
parent13295f52fb5936b237a994e75311fe18612c73c4 (diff)
downloadFreeBSD-src-9d5ffb47ff56597309eb2939cc97b1df4d616797.zip
FreeBSD-src-9d5ffb47ff56597309eb2939cc97b1df4d616797.tar.gz
Merge remote-tracking branch 'origin/stable/10' into devel
Diffstat (limited to 'sys/kern/vfs_mount.c')
-rw-r--r--sys/kern/vfs_mount.c21
1 files changed, 18 insertions, 3 deletions
diff --git a/sys/kern/vfs_mount.c b/sys/kern/vfs_mount.c
index 3ca995f..f5f522e 100644
--- a/sys/kern/vfs_mount.c
+++ b/sys/kern/vfs_mount.c
@@ -1222,7 +1222,6 @@ dounmount(struct mount *mp, int flags, struct thread *td)
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, struct thread *td)
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, struct thread *td)
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, struct thread *td)
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;
OpenPOWER on IntegriCloud