- We can not hold a vnode lock while we do a lookup. Search for and load
modules prior to looking up the directory which we will cover to avoid this problem in mount. - We must hold the coveredvp locked before we can busy the mountpoint to prevent a lock order reversal with the vfs_busy() in lookup which holds the directory lock prior to doing a vfs_busy(). The directory lock is required to safely clear the v_mountedhere field on the directory. MFC After: 1 week
This commit is contained in:
parent
8a7cd2fdfb
commit
a4aeaefe5a
@ -466,6 +466,7 @@ vfs_mount_destroy(struct mount *mp, struct thread *td)
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
vfs_unbusy(mp, td);
|
||||||
MNT_ILOCK(mp);
|
MNT_ILOCK(mp);
|
||||||
for (i = 0; mp->mnt_ref && i < 3; i++)
|
for (i = 0; mp->mnt_ref && i < 3; i++)
|
||||||
msleep(mp, MNT_MTX(mp), PVFS, "mntref", hz);
|
msleep(mp, MNT_MTX(mp), PVFS, "mntref", hz);
|
||||||
@ -501,7 +502,6 @@ vfs_mount_destroy(struct mount *mp, struct thread *td)
|
|||||||
mp->mnt_vfc->vfc_refcount--;
|
mp->mnt_vfc->vfc_refcount--;
|
||||||
if (!TAILQ_EMPTY(&mp->mnt_nvnodelist))
|
if (!TAILQ_EMPTY(&mp->mnt_nvnodelist))
|
||||||
panic("unmount: dangling vnode");
|
panic("unmount: dangling vnode");
|
||||||
vfs_unbusy(mp,td);
|
|
||||||
lockdestroy(&mp->mnt_lock);
|
lockdestroy(&mp->mnt_lock);
|
||||||
MNT_ILOCK(mp);
|
MNT_ILOCK(mp);
|
||||||
if (mp->mnt_kern_flag & MNTK_MWAIT)
|
if (mp->mnt_kern_flag & MNTK_MWAIT)
|
||||||
@ -741,7 +741,6 @@ vfs_domount(
|
|||||||
struct nameidata nd;
|
struct nameidata nd;
|
||||||
|
|
||||||
mtx_assert(&Giant, MA_OWNED);
|
mtx_assert(&Giant, MA_OWNED);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Be ultra-paranoid about making sure the type and fspath
|
* Be ultra-paranoid about making sure the type and fspath
|
||||||
* variables will fit in our mp buffers, including the
|
* variables will fit in our mp buffers, including the
|
||||||
@ -770,6 +769,18 @@ vfs_domount(
|
|||||||
*/
|
*/
|
||||||
if (suser(td) != 0)
|
if (suser(td) != 0)
|
||||||
fsflags |= MNT_NOSUID | MNT_USER;
|
fsflags |= MNT_NOSUID | MNT_USER;
|
||||||
|
|
||||||
|
/* Load KLDs before we lock the covered vnode to avoid reversals. */
|
||||||
|
vfsp = NULL;
|
||||||
|
if ((fsflags & MNT_UPDATE) == 0) {
|
||||||
|
/* Don't try to load KLDs if we're mounting the root. */
|
||||||
|
if (fsflags & MNT_ROOTFS)
|
||||||
|
vfsp = vfs_byname(fstype);
|
||||||
|
else
|
||||||
|
vfsp = vfs_byname_kld(fstype, td, &error);
|
||||||
|
if (vfsp == NULL)
|
||||||
|
return (ENODEV);
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* Get vnode to be covered
|
* Get vnode to be covered
|
||||||
*/
|
*/
|
||||||
@ -848,19 +859,6 @@ vfs_domount(
|
|||||||
vput(vp);
|
vput(vp);
|
||||||
return (ENOTDIR);
|
return (ENOTDIR);
|
||||||
}
|
}
|
||||||
/* Don't try to load KLDs if we're mounting the root. */
|
|
||||||
if (fsflags & MNT_ROOTFS) {
|
|
||||||
if ((vfsp = vfs_byname(fstype)) == NULL) {
|
|
||||||
vput(vp);
|
|
||||||
return (ENODEV);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
vfsp = vfs_byname_kld(fstype, td, &error);
|
|
||||||
if (vfsp == NULL) {
|
|
||||||
vput(vp);
|
|
||||||
return (error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
VI_LOCK(vp);
|
VI_LOCK(vp);
|
||||||
if ((vp->v_iflag & VI_MOUNT) != 0 ||
|
if ((vp->v_iflag & VI_MOUNT) != 0 ||
|
||||||
vp->v_mountedhere != NULL) {
|
vp->v_mountedhere != NULL) {
|
||||||
@ -1069,9 +1067,13 @@ dounmount(mp, flags, td)
|
|||||||
|
|
||||||
mtx_assert(&Giant, MA_OWNED);
|
mtx_assert(&Giant, MA_OWNED);
|
||||||
|
|
||||||
|
if ((coveredvp = mp->mnt_vnodecovered) != NULL)
|
||||||
|
vn_lock(coveredvp, LK_EXCLUSIVE | LK_RETRY, td);
|
||||||
MNT_ILOCK(mp);
|
MNT_ILOCK(mp);
|
||||||
if (mp->mnt_kern_flag & MNTK_UNMOUNT) {
|
if (mp->mnt_kern_flag & MNTK_UNMOUNT) {
|
||||||
MNT_IUNLOCK(mp);
|
MNT_IUNLOCK(mp);
|
||||||
|
if (coveredvp)
|
||||||
|
VOP_UNLOCK(coveredvp, 0, td);
|
||||||
return (EBUSY);
|
return (EBUSY);
|
||||||
}
|
}
|
||||||
mp->mnt_kern_flag |= MNTK_UNMOUNT;
|
mp->mnt_kern_flag |= MNTK_UNMOUNT;
|
||||||
@ -1086,6 +1088,8 @@ dounmount(mp, flags, td)
|
|||||||
if (mp->mnt_kern_flag & MNTK_MWAIT)
|
if (mp->mnt_kern_flag & MNTK_MWAIT)
|
||||||
wakeup(mp);
|
wakeup(mp);
|
||||||
MNT_IUNLOCK(mp);
|
MNT_IUNLOCK(mp);
|
||||||
|
if (coveredvp)
|
||||||
|
VOP_UNLOCK(coveredvp, 0, td);
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
vn_start_write(NULL, &mp, V_WAIT);
|
vn_start_write(NULL, &mp, V_WAIT);
|
||||||
@ -1141,17 +1145,19 @@ dounmount(mp, flags, td)
|
|||||||
if (mp->mnt_kern_flag & MNTK_MWAIT)
|
if (mp->mnt_kern_flag & MNTK_MWAIT)
|
||||||
wakeup(mp);
|
wakeup(mp);
|
||||||
MNT_IUNLOCK(mp);
|
MNT_IUNLOCK(mp);
|
||||||
|
if (coveredvp)
|
||||||
|
VOP_UNLOCK(coveredvp, 0, td);
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
mtx_lock(&mountlist_mtx);
|
mtx_lock(&mountlist_mtx);
|
||||||
TAILQ_REMOVE(&mountlist, mp, mnt_list);
|
TAILQ_REMOVE(&mountlist, mp, mnt_list);
|
||||||
if ((coveredvp = mp->mnt_vnodecovered) != NULL)
|
|
||||||
coveredvp->v_mountedhere = NULL;
|
|
||||||
mtx_unlock(&mountlist_mtx);
|
mtx_unlock(&mountlist_mtx);
|
||||||
|
if (coveredvp != NULL) {
|
||||||
|
coveredvp->v_mountedhere = NULL;
|
||||||
|
vput(coveredvp);
|
||||||
|
}
|
||||||
vfs_event_signal(NULL, VQ_UNMOUNT, 0);
|
vfs_event_signal(NULL, VQ_UNMOUNT, 0);
|
||||||
vfs_mount_destroy(mp, td);
|
vfs_mount_destroy(mp, td);
|
||||||
if (coveredvp != NULL)
|
|
||||||
vrele(coveredvp);
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user