Date: Wed, 22 Jun 2016 09:10:52 +0000 (UTC) From: Konstantin Belousov <kib@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r302079 - stable/10/sys/kern Message-ID: <201606220910.u5M9Aric019061@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
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;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201606220910.u5M9Aric019061>