mirror of
https://github.com/freebsd/freebsd-src
synced 2024-07-23 19:28:36 +00:00
unionfs: upgrade the vnode lock during fsync() if necessary
If the underlying upper FS supports shared locking for write ops, as is the case with ZFS, VOP_FSYNC() may only be called with the vnode lock held shared. In this case, temporarily upgrade the lock for those unionfs maintenance operations which require exclusive locking. While here, make unionfs inherit the upper FS' support for shared write locking. Since the upper FS is the target of VOP_GETWRITEMOUNT() this is what will dictate the locking behavior of any unionfs caller that uses vn_start_write() + vn_lktype_write(), so unionfs must be prepared for the caller to only hold a shared vnode lock in these cases. Found in local testing of unionfs atop ZFS with DEBUG_VFS_LOCKS. MFC after: 2 weeks Reviewed by: kib, olce Differential Revision: https://reviews.freebsd.org/D43817
This commit is contained in:
parent
9530182e37
commit
2656fc29be
|
@ -348,7 +348,8 @@ unionfs_domount(struct mount *mp)
|
|||
if ((ump->um_lowermp->mnt_flag & MNT_LOCAL) != 0 &&
|
||||
(ump->um_uppermp->mnt_flag & MNT_LOCAL) != 0)
|
||||
mp->mnt_flag |= MNT_LOCAL;
|
||||
mp->mnt_kern_flag |= MNTK_NOMSYNC | MNTK_UNIONFS;
|
||||
mp->mnt_kern_flag |= MNTK_NOMSYNC | MNTK_UNIONFS |
|
||||
(ump->um_uppermp->mnt_kern_flag & MNTK_SHARED_WRITES);
|
||||
MNT_IUNLOCK(mp);
|
||||
|
||||
/*
|
||||
|
|
|
@ -998,14 +998,22 @@ unionfs_fsync(struct vop_fsync_args *ap)
|
|||
struct unionfs_node *unp;
|
||||
struct unionfs_node_status *unsp;
|
||||
struct vnode *ovp;
|
||||
enum unionfs_lkupgrade lkstatus;
|
||||
|
||||
KASSERT_UNIONFS_VNODE(ap->a_vp);
|
||||
|
||||
unp = VTOUNIONFS(ap->a_vp);
|
||||
lkstatus = unionfs_upgrade_lock(ap->a_vp);
|
||||
if (lkstatus == UNIONFS_LKUPGRADE_DOOMED) {
|
||||
unionfs_downgrade_lock(ap->a_vp, lkstatus);
|
||||
return (ENOENT);
|
||||
}
|
||||
unionfs_get_node_status(unp, ap->a_td, &unsp);
|
||||
ovp = (unsp->uns_upper_opencnt ? unp->un_uppervp : unp->un_lowervp);
|
||||
unionfs_tryrem_node_status(unp, unsp);
|
||||
|
||||
unionfs_downgrade_lock(ap->a_vp, lkstatus);
|
||||
|
||||
if (ovp == NULLVP)
|
||||
return (EBADF);
|
||||
|
||||
|
|
Loading…
Reference in a new issue