vn_delayed_setsize(): post-commit review' changes

Handle doomed vnodes after LK_RETRY.
Rename the flag from VI_DELAYEDSSZ to VI_DELAYED_SETSIZE.
Change signature of vn_lock_delayed_setsize() to take flatten values
list instead of vop args structure.
__predict_true() for VI_DELAYED_SETSIZE not set.
Minor editings like removing tautological assert, and sorting items.

Noted by:	markj
Fixes:	45117ffcd5
Reviewed by:	markj, rmacklem
Tested by:	pho
Sponsored by:	The FreeBSD Foundation
MFC after:	1 week
Differential revision:	https://reviews.freebsd.org/D55681
This commit is contained in:
Konstantin Belousov
2026-03-06 02:18:11 +02:00
parent a2b601343b
commit 92d7808d88
4 changed files with 35 additions and 37 deletions
+3 -3
View File
@@ -55,6 +55,9 @@ struct vop_vector dead_vnodeops = {
.vop_bmap = VOP_EBADF, .vop_bmap = VOP_EBADF,
.vop_close = dead_close, .vop_close = dead_close,
.vop_create = VOP_PANIC, .vop_create = VOP_PANIC,
.vop_delayed_setsize = VOP_NULL,
.vop_fplookup_symlink = VOP_EOPNOTSUPP,
.vop_fplookup_vexec = VOP_EOPNOTSUPP,
.vop_getattr = VOP_EBADF, .vop_getattr = VOP_EBADF,
.vop_getwritemount = dead_getwritemount, .vop_getwritemount = dead_getwritemount,
.vop_inactive = VOP_NULL, .vop_inactive = VOP_NULL,
@@ -78,9 +81,6 @@ struct vop_vector dead_vnodeops = {
.vop_vptocnp = VOP_EBADF, .vop_vptocnp = VOP_EBADF,
.vop_unset_text = dead_unset_text, .vop_unset_text = dead_unset_text,
.vop_write = dead_write, .vop_write = dead_write,
.vop_fplookup_vexec = VOP_EOPNOTSUPP,
.vop_fplookup_symlink = VOP_EOPNOTSUPP,
.vop_delayed_setsize = VOP_NULL,
}; };
VFS_VOP_VECTOR_REGISTER(dead_vnodeops); VFS_VOP_VECTOR_REGISTER(dead_vnodeops);
+1 -1
View File
@@ -646,7 +646,7 @@ ncl_pager_setsize(struct vnode *vp, u_quad_t *nsizep)
(curthread->td_pflags2 & TDP2_SBPAGES) == 0) (curthread->td_pflags2 & TDP2_SBPAGES) == 0)
setnsize = true; setnsize = true;
else else
vn_delay_setsize(vp); vn_delayed_setsize(vp);
} }
if (nsizep == NULL) { if (nsizep == NULL) {
NFSUNLOCKNODE(np); NFSUNLOCKNODE(np);
+25 -27
View File
@@ -1960,25 +1960,25 @@ _vn_lock_fallback(struct vnode *vp, int flags, const char *file, int line,
} }
static int static int
vn_lock_delayed_setsize(struct vop_lock1_args *ap) vn_lock_delayed_setsize(struct vnode *vp, int flags, const char *file, int line)
{ {
struct vnode *vp; struct vop_lock1_args ap;
int error, lktype; int error, lktype;
bool onfault; bool onfault;
vp = ap->a_vp; ASSERT_VOP_LOCKED(vp, "vn_lock_delayed_setsize");
lktype = ap->a_flags & LK_TYPE_MASK; lktype = flags & LK_TYPE_MASK;
if (vp->v_op == &dead_vnodeops) if (vp->v_op == &dead_vnodeops)
return (0); return (0);
VI_LOCK(vp); VI_LOCK(vp);
if ((vp->v_iflag & VI_DELAYEDSSZ) == 0 || (lktype != LK_SHARED && if ((vp->v_iflag & VI_DELAYED_SETSIZE) == 0 || (lktype != LK_SHARED &&
lktype != LK_EXCLUSIVE && lktype != LK_UPGRADE && lktype != LK_EXCLUSIVE && lktype != LK_UPGRADE &&
lktype != LK_TRYUPGRADE)) { lktype != LK_TRYUPGRADE)) {
VI_UNLOCK(vp); VI_UNLOCK(vp);
return (0); return (0);
} }
onfault = (ap->a_flags & LK_EATTR_MASK) == LK_NOWAIT && onfault = (flags & LK_EATTR_MASK) == LK_NOWAIT &&
(ap->a_flags & LK_INIT_MASK) == LK_CANRECURSE && (flags & LK_INIT_MASK) == LK_CANRECURSE &&
(lktype == LK_SHARED || lktype == LK_EXCLUSIVE); (lktype == LK_SHARED || lktype == LK_EXCLUSIVE);
if (onfault && vp->v_vnlock->lk_recurse == 0) { if (onfault && vp->v_vnlock->lk_recurse == 0) {
/* /*
@@ -1990,35 +1990,38 @@ vn_lock_delayed_setsize(struct vop_lock1_args *ap)
VOP_UNLOCK(vp); VOP_UNLOCK(vp);
return (EBUSY); return (EBUSY);
} }
if ((ap->a_flags & LK_NOWAIT) != 0 || if ((flags & LK_NOWAIT) != 0 ||
(lktype == LK_SHARED && vp->v_vnlock->lk_recurse > 0)) { (lktype == LK_SHARED && vp->v_vnlock->lk_recurse > 0)) {
VI_UNLOCK(vp); VI_UNLOCK(vp);
return (0); return (0);
} }
if (lktype == LK_SHARED) { if (lktype == LK_SHARED) {
VOP_UNLOCK(vp); VOP_UNLOCK(vp);
ap->a_flags &= ~LK_TYPE_MASK; ap.a_gen.a_desc = &vop_lock1_desc;
ap->a_flags |= LK_EXCLUSIVE | LK_INTERLOCK; ap.a_vp = vp;
error = VOP_LOCK1_APV(&default_vnodeops, ap); ap.a_flags = (flags & ~LK_TYPE_MASK) | LK_EXCLUSIVE |
LK_INTERLOCK;
ap.a_file = file;
ap.a_line = line;
error = VOP_LOCK1_APV(&default_vnodeops, &ap);
if (error != 0 || vp->v_op == &dead_vnodeops) if (error != 0 || vp->v_op == &dead_vnodeops)
return (error); return (error);
if (vp->v_data == NULL) if (vp->v_data == NULL)
goto downgrade; goto downgrade;
MPASS(vp->v_data != NULL);
VI_LOCK(vp); VI_LOCK(vp);
if ((vp->v_iflag & VI_DELAYEDSSZ) == 0) { if ((vp->v_iflag & VI_DELAYED_SETSIZE) == 0) {
VI_UNLOCK(vp); VI_UNLOCK(vp);
goto downgrade; goto downgrade;
} }
} }
vp->v_iflag &= ~VI_DELAYEDSSZ; vn_clear_delayed_setsize_locked(vp);
VI_UNLOCK(vp); VI_UNLOCK(vp);
VOP_DELAYED_SETSIZE(vp); VOP_DELAYED_SETSIZE(vp);
downgrade: downgrade:
if (lktype == LK_SHARED) { if (lktype == LK_SHARED) {
ap->a_flags &= ~(LK_TYPE_MASK | LK_INTERLOCK); ap.a_flags &= ~(LK_TYPE_MASK | LK_INTERLOCK);
ap->a_flags |= LK_DOWNGRADE; ap.a_flags |= LK_DOWNGRADE;
(void)VOP_LOCK1_APV(&default_vnodeops, ap); (void)VOP_LOCK1_APV(&default_vnodeops, &ap);
} }
return (0); return (0);
} }
@@ -2026,7 +2029,6 @@ vn_lock_delayed_setsize(struct vop_lock1_args *ap)
int int
_vn_lock(struct vnode *vp, int flags, const char *file, int line) _vn_lock(struct vnode *vp, int flags, const char *file, int line)
{ {
struct vop_lock1_args ap;
int error; int error;
VNASSERT((flags & LK_TYPE_MASK) != 0, vp, VNASSERT((flags & LK_TYPE_MASK) != 0, vp,
@@ -2034,15 +2036,11 @@ _vn_lock(struct vnode *vp, int flags, const char *file, int line)
VNPASS(vp->v_holdcnt > 0, vp); VNPASS(vp->v_holdcnt > 0, vp);
error = VOP_LOCK1(vp, flags, file, line); error = VOP_LOCK1(vp, flags, file, line);
if (__predict_false(error != 0 || VN_IS_DOOMED(vp))) if (__predict_false(error != 0 || VN_IS_DOOMED(vp)))
return (_vn_lock_fallback(vp, flags, file, line, error)); error = _vn_lock_fallback(vp, flags, file, line, error);
if (__predict_false((vp->v_iflag & VI_DELAYEDSSZ) == 0)) if (error != 0 || __predict_true((atomic_load_short(&vp->v_iflag) &
return (0); VI_DELAYED_SETSIZE) == 0))
ap.a_gen.a_desc = &vop_lock1_desc; return (error);
ap.a_vp = vp; return (vn_lock_delayed_setsize(vp, flags, file, line));
ap.a_flags = flags;
ap.a_file = file;
ap.a_line = line;
return (vn_lock_delayed_setsize(&ap));
} }
/* /*
+6 -6
View File
@@ -268,7 +268,7 @@ _Static_assert(sizeof(struct vnode) <= 448, "vnode size crosses 448 bytes");
#define VI_DEFINACT 0x0010 /* deferred inactive */ #define VI_DEFINACT 0x0010 /* deferred inactive */
#define VI_FOPENING 0x0020 /* In open, with opening process having the #define VI_FOPENING 0x0020 /* In open, with opening process having the
first right to advlock file */ first right to advlock file */
#define VI_DELAYEDSSZ 0x0040 /* Delayed setsize */ #define VI_DELAYED_SETSIZE 0x0040 /* Delayed setsize */
#define VV_ROOT 0x0001 /* root of its filesystem */ #define VV_ROOT 0x0001 /* root of its filesystem */
#define VV_ISTTY 0x0002 /* vnode represents a tty */ #define VV_ISTTY 0x0002 /* vnode represents a tty */
@@ -1253,17 +1253,17 @@ vn_get_state(struct vnode *vp)
}) })
static inline void static inline void
vn_delay_setsize_locked(struct vnode *vp) vn_delayed_setsize_locked(struct vnode *vp)
{ {
ASSERT_VI_LOCKED(vp, "delayed_setsize"); ASSERT_VI_LOCKED(vp, "delayed_setsize");
vp->v_iflag |= VI_DELAYEDSSZ; vp->v_iflag |= VI_DELAYED_SETSIZE;
} }
static inline void static inline void
vn_delay_setsize(struct vnode *vp) vn_delayed_setsize(struct vnode *vp)
{ {
VI_LOCK(vp); VI_LOCK(vp);
vn_delay_setsize_locked(vp); vn_delayed_setsize_locked(vp);
VI_UNLOCK(vp); VI_UNLOCK(vp);
} }
@@ -1271,7 +1271,7 @@ static inline void
vn_clear_delayed_setsize_locked(struct vnode *vp) vn_clear_delayed_setsize_locked(struct vnode *vp)
{ {
ASSERT_VI_LOCKED(vp, "delayed_setsize"); ASSERT_VI_LOCKED(vp, "delayed_setsize");
vp->v_iflag &= ~VI_DELAYEDSSZ; vp->v_iflag &= ~VI_DELAYED_SETSIZE;
} }
static inline void static inline void