Date: Thu, 25 Feb 2021 20:52:29 GMT From: Konstantin Belousov <kib@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org Subject: git: 2e4940262c71 - releng/13.0 - Stop ignoring ERELOOKUP from VOP_INACTIVE() Message-ID: <202102252052.11PKqTaj079445@gitrepo.freebsd.org>
next in thread | raw e-mail | index | archive | help
The branch releng/13.0 has been updated by kib: URL: https://cgit.FreeBSD.org/src/commit/?id=2e4940262c719672763181a6a735b17a6fb50b64 commit 2e4940262c719672763181a6a735b17a6fb50b64 Author: Konstantin Belousov <kib@FreeBSD.org> AuthorDate: 2021-01-30 19:17:29 +0000 Commit: Konstantin Belousov <kib@FreeBSD.org> CommitDate: 2021-02-25 20:49:49 +0000 Stop ignoring ERELOOKUP from VOP_INACTIVE() Approved by: re (delphij, gjb) (cherry picked from commit b59a8e63d6bf9092419b7a421c655d0ae2099662) --- sys/kern/vfs_subr.c | 47 ++++++++++++++++++++++++++++++++-------------- sys/sys/vnode.h | 3 ++- sys/ufs/ffs/ffs_snapshot.c | 8 +++++++- 3 files changed, 42 insertions(+), 16 deletions(-) diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index 047e4c54f0c5..04cd0e0175f9 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -3159,9 +3159,21 @@ vput_final(struct vnode *vp, enum vput_op func) break; } if (error == 0) { - vinactive(vp); - if (want_unlock) - VOP_UNLOCK(vp); + if (func == VUNREF) { + VNASSERT((vp->v_vflag & VV_UNREF) == 0, vp, + ("recursive vunref")); + vp->v_vflag |= VV_UNREF; + } + for (;;) { + error = vinactive(vp); + if (want_unlock) + VOP_UNLOCK(vp); + if (error != ERELOOKUP || !want_unlock) + break; + VOP_LOCK(vp, LK_EXCLUSIVE); + } + if (func == VUNREF) + vp->v_vflag &= ~VV_UNREF; vdropl(vp); } else { vdefer_inactive(vp); @@ -3546,10 +3558,11 @@ vdropl(struct vnode *vp) * Call VOP_INACTIVE on the vnode and manage the DOINGINACT and OWEINACT * flags. DOINGINACT prevents us from recursing in calls to vinactive. */ -static void +static int vinactivef(struct vnode *vp) { struct vm_object *obj; + int error; ASSERT_VOP_ELOCKED(vp, "vinactive"); ASSERT_VI_LOCKED(vp, "vinactive"); @@ -3575,14 +3588,15 @@ vinactivef(struct vnode *vp) vm_object_page_clean(obj, 0, 0, 0); VM_OBJECT_WUNLOCK(obj); } - VOP_INACTIVE(vp); + error = VOP_INACTIVE(vp); VI_LOCK(vp); VNASSERT(vp->v_iflag & VI_DOINGINACT, vp, ("vinactive: lost VI_DOINGINACT")); vp->v_iflag &= ~VI_DOINGINACT; + return (error); } -void +int vinactive(struct vnode *vp) { @@ -3591,14 +3605,14 @@ vinactive(struct vnode *vp) CTR2(KTR_VFS, "%s: vp %p", __func__, vp); if ((vp->v_iflag & VI_OWEINACT) == 0) - return; + return (0); if (vp->v_iflag & VI_DOINGINACT) - return; + return (0); if (vp->v_usecount > 0) { vp->v_iflag &= ~VI_OWEINACT; - return; + return (0); } - vinactivef(vp); + return (vinactivef(vp)); } /* @@ -3911,10 +3925,15 @@ vgonel(struct vnode *vp) */ if (active) VOP_CLOSE(vp, FNONBLOCK, NOCRED, td); - if ((oweinact || active) && !doinginact) { - VI_LOCK(vp); - vinactivef(vp); - VI_UNLOCK(vp); + if (!doinginact) { + do { + if (oweinact || active) { + VI_LOCK(vp); + vinactivef(vp); + oweinact = (vp->v_iflag & VI_OWEINACT) != 0; + VI_UNLOCK(vp); + } + } while (oweinact); } if (vp->v_type == VSOCK) vfs_unp_reclaim(vp); diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h index 78fbec1bd0ba..639a16881e09 100644 --- a/sys/sys/vnode.h +++ b/sys/sys/vnode.h @@ -269,6 +269,7 @@ struct xvnode { #define VV_MD 0x0800 /* vnode backs the md device */ #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 VMP_LAZYLIST 0x0001 /* Vnode is on mnt's lazy list */ @@ -710,7 +711,7 @@ void vgone(struct vnode *vp); void vhold(struct vnode *); void vholdnz(struct vnode *); bool vhold_smr(struct vnode *); -void vinactive(struct vnode *vp); +int vinactive(struct vnode *vp); int vinvalbuf(struct vnode *vp, int save, int slpflag, int slptimeo); int vtruncbuf(struct vnode *vp, off_t length, int blksize); void v_inval_buf_range(struct vnode *vp, daddr_t startlbn, daddr_t endlbn, diff --git a/sys/ufs/ffs/ffs_snapshot.c b/sys/ufs/ffs/ffs_snapshot.c index b5daec14decf..72c8061917d8 100644 --- a/sys/ufs/ffs/ffs_snapshot.c +++ b/sys/ufs/ffs/ffs_snapshot.c @@ -2595,6 +2595,7 @@ process_deferred_inactive(struct mount *mp) continue; } vholdl(vp); +retry_vnode: error = vn_lock(vp, LK_EXCLUSIVE | LK_INTERLOCK); if (error != 0) { vdrop(vp); @@ -2609,7 +2610,12 @@ process_deferred_inactive(struct mount *mp) UFS_INODE_SET_FLAG(ip, IN_MODIFIED); } VI_LOCK(vp); - vinactive(vp); + error = vinactive(vp); + if (error == ERELOOKUP && vp->v_usecount == 0) { + VI_UNLOCK(vp); + VOP_UNLOCK(vp); + goto retry_vnode; + } VI_UNLOCK(vp); VOP_UNLOCK(vp); vdrop(vp);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202102252052.11PKqTaj079445>