Changeset View
Changeset View
Standalone View
Standalone View
sys/fs/unionfs/union_vfsops.c
Show First 20 Lines • Show All 304 Lines • ▼ Show 20 Lines | if (lowermp != NULL) | ||||
vfs_unregister_upper(lowermp, &ump->um_lower_link); | vfs_unregister_upper(lowermp, &ump->um_lower_link); | ||||
if (uppermp != NULL) | if (uppermp != NULL) | ||||
vfs_unregister_upper(uppermp, &ump->um_upper_link); | vfs_unregister_upper(uppermp, &ump->um_upper_link); | ||||
free(ump, M_UNIONFSMNT); | free(ump, M_UNIONFSMNT); | ||||
mp->mnt_data = NULL; | mp->mnt_data = NULL; | ||||
return (ENOENT); | return (ENOENT); | ||||
} | } | ||||
/* | |||||
* 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. | |||||
*/ | |||||
if (!below) { | |||||
vn_lock(mp->mnt_vnodecovered, LK_EXCLUSIVE | LK_RETRY); | |||||
mp->mnt_vnodecovered->v_vflag |= VV_CROSSLOCK; | |||||
VOP_UNLOCK(mp->mnt_vnodecovered); | |||||
} | |||||
MNT_ILOCK(mp); | MNT_ILOCK(mp); | ||||
if ((lowermp->mnt_flag & MNT_LOCAL) != 0 && | if ((lowermp->mnt_flag & MNT_LOCAL) != 0 && | ||||
(uppermp->mnt_flag & MNT_LOCAL) != 0) | (uppermp->mnt_flag & MNT_LOCAL) != 0) | ||||
mp->mnt_flag |= MNT_LOCAL; | mp->mnt_flag |= MNT_LOCAL; | ||||
mp->mnt_kern_flag |= MNTK_NOMSYNC | MNTK_UNIONFS; | mp->mnt_kern_flag |= MNTK_NOMSYNC | MNTK_UNIONFS; | ||||
MNT_IUNLOCK(mp); | MNT_IUNLOCK(mp); | ||||
/* | /* | ||||
Show All 36 Lines | for (freeing = 0; (error = vflush(mp, 1, flags, curthread)) != 0;) { | ||||
if (num == freeing) | if (num == freeing) | ||||
break; | break; | ||||
freeing = num; | freeing = num; | ||||
} | } | ||||
if (error) | if (error) | ||||
return (error); | return (error); | ||||
vn_lock(mp->mnt_vnodecovered, LK_EXCLUSIVE | LK_RETRY); | |||||
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_lowervp->v_mount, &ump->um_lower_link); | ||||
vfs_unregister_upper(ump->um_uppervp->v_mount, &ump->um_upper_link); | vfs_unregister_upper(ump->um_uppervp->v_mount, &ump->um_upper_link); | ||||
free(ump, M_UNIONFSMNT); | free(ump, M_UNIONFSMNT); | ||||
mp->mnt_data = NULL; | mp->mnt_data = NULL; | ||||
return (0); | return (0); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 174 Lines • Show Last 20 Lines |