commit 23bb9cddaef6f06521efe4f8340f992d8a0b362f Author: Mateusz Guzik Date: Tue Jan 19 19:03:41 2021 +0100 vfs: VIRF_MODIFY WIP diff --git a/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_znode.c b/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_znode.c index 6a21623c5f67..644692ae48fb 100644 --- a/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_znode.c +++ b/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_znode.c @@ -431,6 +431,7 @@ zfs_znode_alloc(zfsvfs_t *zfsvfs, dmu_buf_t *db, int blksz, zfs_znode_free_kmem(zp); return (NULL); } + vn_irflag_set_new(vp, VIRF_MODIFY); zp->z_vnode = vp; vp->v_data = zp; diff --git a/sys/fs/tmpfs/tmpfs_subr.c b/sys/fs/tmpfs/tmpfs_subr.c index c74981db0f58..262714db51ec 100644 --- a/sys/fs/tmpfs/tmpfs_subr.c +++ b/sys/fs/tmpfs/tmpfs_subr.c @@ -671,6 +671,8 @@ tmpfs_alloc_vp(struct mount *mp, struct tmpfs_node *node, int lkflag, goto unlock; MPASS(vp != NULL); + vn_irflag_set_new(vp, VIRF_MODIFY); + /* lkflag is ignored, the lock is exclusive */ (void) vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); diff --git a/sys/kern/vfs_cache.c b/sys/kern/vfs_cache.c index 5a1ebffece05..4df83e751ce6 100644 --- a/sys/kern/vfs_cache.c +++ b/sys/kern/vfs_cache.c @@ -4154,6 +4154,14 @@ cache_fplookup_final_modifying(struct cache_fpl *fpl) return (cache_fpl_handled_error(fpl, EEXIST)); } + /* + * Hack: UFS seems to be running into deadlocks, don't use the + * feature. + */ + if ((vn_irflag_read(fpl->dvp) & VIRF_MODIFY) == 0) { + return (cache_fpl_partial(fpl)); + } + /* * Secure access to dvp; check cache_fplookup_partial_setup for * reasoning. diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index 8461fd0d49b5..2e67dafa4424 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -6823,6 +6823,18 @@ vn_seqc_write_end_free(struct vnode *vp) VNPASS(vp->v_seqc_users == 1, vp); } + +/* + * Only to be called after getnewvnode and before publishing the vnode. + */ +void +vn_irflag_set_new(struct vnode *vp, short toset) +{ + + VNPASS(vp->v_irflag == 0, vp); + atomic_store_short(&vp->v_irflag, toset); +} + void vn_irflag_set_locked(struct vnode *vp, short toset) { diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h index 0eadfec02313..9034c44d2df9 100644 --- a/sys/sys/vnode.h +++ b/sys/sys/vnode.h @@ -247,6 +247,7 @@ struct xvnode { #define VIRF_PGREAD 0x0002 /* Direct reads from the page cache are permitted, never cleared once set */ #define VIRF_MOUNTPOINT 0x0004 /* This vnode is mounted on */ +#define VIRF_MODIFY 0x0008 /* Filesystem supports modification from LL */ #define VI_TEXT_REF 0x0001 /* Text ref grabbed use ref */ #define VI_MOUNT 0x0002 /* Mount in progress */ @@ -802,6 +803,7 @@ void vn_seqc_write_end(struct vnode *vp); rangelock_trywlock(&(vp)->v_rl, (start), (end), VI_MTX(vp)) #define vn_irflag_read(vp) atomic_load_short(&(vp)->v_irflag) +void vn_irflag_set_new(struct vnode *vp, short toset); void vn_irflag_set_locked(struct vnode *vp, short toset); void vn_irflag_set(struct vnode *vp, short toset); void vn_irflag_set_cond_locked(struct vnode *vp, short toset);