diff --git a/sys/fs/nullfs/null_vfsops.c b/sys/fs/nullfs/null_vfsops.c --- a/sys/fs/nullfs/null_vfsops.c +++ b/sys/fs/nullfs/null_vfsops.c @@ -212,12 +212,6 @@ &xmp->notify_node); } - if (lowerrootvp == mp->mnt_vnodecovered) { - vn_lock(lowerrootvp, LK_EXCLUSIVE | LK_RETRY | LK_CANRECURSE); - lowerrootvp->v_vflag |= VV_CROSSLOCK; - VOP_UNLOCK(lowerrootvp); - } - MNT_ILOCK(mp); if ((xmp->nullm_flags & NULLM_CACHE) != 0) { mp->mnt_kern_flag |= lowerrootvp->v_mount->mnt_kern_flag & @@ -276,11 +270,6 @@ vfs_unregister_for_notification(mntdata->nullm_vfs, &mntdata->notify_node); } - if (mntdata->nullm_lowerrootvp == mp->mnt_vnodecovered) { - vn_lock(mp->mnt_vnodecovered, LK_EXCLUSIVE | LK_RETRY | LK_CANRECURSE); - mp->mnt_vnodecovered->v_vflag &= ~VV_CROSSLOCK; - VOP_UNLOCK(mp->mnt_vnodecovered); - } vfs_unregister_upper(mntdata->nullm_vfs, &mntdata->upper_node); vrele(mntdata->nullm_lowerrootvp); mp->mnt_data = NULL; diff --git a/sys/fs/unionfs/union_vfsops.c b/sys/fs/unionfs/union_vfsops.c --- a/sys/fs/unionfs/union_vfsops.c +++ b/sys/fs/unionfs/union_vfsops.c @@ -325,28 +325,13 @@ } /* - * Specify that the covered vnode lock should remain held while - * lookup() performs the cross-mount walk. This prevents a lock-order - * reversal between the covered vnode lock (which is also locked by - * unionfs_lock()) and the mountpoint's busy count. Without this, - * unmount will lock the covered vnode lock (directly through the - * covered vnode) and wait for the busy count to drain, while a - * concurrent lookup will increment the busy count and then lock - * the covered vnode lock (indirectly through unionfs_lock()). - * - * Note that we can't yet use this facility for the 'below' case - * in which the upper vnode is the covered vnode, because that would - * introduce a different LOR in which the cross-mount lookup would - * effectively hold the upper vnode lock before acquiring the lower - * vnode lock, while an unrelated lock operation would still acquire - * the lower vnode lock before the upper vnode lock, which is the - * order unionfs currently requires. + * For the 'below' case in which the upper vnode is the covered vnode, + * there is currently a LOR in which the cross-mount lookup effectively + * leads to holding the upper vnode lock before acquiring the lower + * vnode lock, while an unrelated lock operation would still acquire the + * lower vnode lock before the upper vnode lock, which is the order + * unionfs currently requires. */ - if (!below) { - vn_lock(mp->mnt_vnodecovered, LK_EXCLUSIVE | LK_RETRY | LK_CANRECURSE); - mp->mnt_vnodecovered->v_vflag |= VV_CROSSLOCK; - VOP_UNLOCK(mp->mnt_vnodecovered); - } MNT_ILOCK(mp); if ((lowermp->mnt_flag & MNT_LOCAL) != 0 && @@ -400,9 +385,6 @@ if (error) return (error); - vn_lock(mp->mnt_vnodecovered, LK_EXCLUSIVE | LK_RETRY | LK_CANRECURSE); - mp->mnt_vnodecovered->v_vflag &= ~VV_CROSSLOCK; - VOP_UNLOCK(mp->mnt_vnodecovered); vfs_unregister_upper(ump->um_lowervp->v_mount, &ump->um_lower_link); vfs_unregister_upper(ump->um_uppervp->v_mount, &ump->um_upper_link); free(ump, M_UNIONFSMNT); diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -777,7 +777,9 @@ * * The lookup() process for namei("/var") illustrates the process: * 1. VOP_LOOKUP() obtains B while A is held - * 2. vfs_busy() obtains a shared lock on F while A and B are held + * 2. vfs_busy(MBF_NOWAIT) tries to obtain a lock on F while A and B are held + * 3. If this didn't work, the lock on B is temporary released, vfs_busy() + * called again to obtain F, and lock on B reacquired via vn_lock(). * 3. vput() releases lock on B * 4. vput() releases lock on A * 5. VFS_ROOT() obtains lock on D while shared lock on F is held @@ -786,12 +788,10 @@ * Attempt to lock A (instead of vp_crossmp) while D is held would * violate the global order, causing deadlocks. * - * dounmount() locks B while F is drained. Note that for stacked - * filesystems, D and B in the example above may be the same lock, - * which introdues potential lock order reversal deadlock between - * dounmount() and step 5 above. These filesystems may avoid the LOR - * by setting VV_CROSSLOCK on the covered vnode so that lock B will - * remain held until after step 5. + * dounmount() doesn't lock B anymore while F is drained. Consequently, there + * is no more a risk of LOR with stacked filesystems, for which D and B in the + * example above may be the same lock (concurrent execution of dounmount() and + * step 5 above). */ int vfs_busy(struct mount *mp, int flags) diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h --- a/sys/sys/vnode.h +++ b/sys/sys/vnode.h @@ -253,7 +253,6 @@ #define VV_FORCEINSMQ 0x1000 /* force the insmntque to succeed */ #define VV_READLINK 0x2000 /* fdescfs linux vnode */ #define VV_UNREF 0x4000 /* vunref, do not drop lock in inactive() */ -#define VV_CROSSLOCK 0x8000 /* vnode lock is shared w/ root mounted here */ #define VMP_LAZYLIST 0x0001 /* Vnode is on mnt's lazy list */