Page MenuHomeFreeBSD

vn_delayed_setsize()
ClosedPublic

Authored by kib on Sat, Feb 28, 4:35 PM.
Tags
None
Referenced Files
F146752488: D55595.id.diff
Thu, Mar 5, 7:28 AM
F146734803: D55595.id172935.diff
Thu, Mar 5, 3:36 AM
Unknown Object (File)
Wed, Mar 4, 11:45 PM
Unknown Object (File)
Tue, Mar 3, 4:16 AM
Unknown Object (File)
Tue, Mar 3, 4:10 AM
Unknown Object (File)
Tue, Mar 3, 2:13 AM
Unknown Object (File)
Mon, Mar 2, 1:02 PM
Unknown Object (File)
Mon, Mar 2, 10:56 AM
Subscribers

Details

Summary
vfs: add VOP_DELAYED_SETSIZE() and related infrastructure

The change generalizes code that was initially developed for nfs client
to handle filesystems that needs to call vnode_pager_setsize() while
only owning the vnode lock shared.  Since vnode pager might need to trim
or extend the vnode vm_object' page queue, the vnode lock for the call
must be owned exclusive.  This is typical for filesystems with remote
authorative source of file attributes, like nfs/p9/fuse.

Handle the conflict by delaying the vnode_pager_setsize() to the next
vnode locking to avoid relock.  But if the next locking request is in
shared mode, lock it exclusively instead, perform the delayed
vnode_pager_setsize() call by doing VOP_DEFAULT_SETSIZE(), and then
downgrade to shared.

Filesystems that opt into the feature must provide the implementation of
VOP_DELAYED_SETSIZE() that actually calls vnode_pager_setsize(), and use
vn_delay_setsize() helper to mark the vnode as requiring the delay call.


nfsclient: convert to use vn_delayed_setsize()

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Skipped
Unit
Tests Skipped

Event Timeline

kib requested review of this revision.Sat, Feb 28, 4:35 PM
20260228 20:28:50 all (1/11): ftruncate3.sh
VNASSERT failed: a->a_gen.a_desc == &vop_lock1_desc not true at vnode_if.c:2095 (VOP_LOCK1_APV)
0xfffffe016a9e6940: type VREG state VSTATE_CONSTRUCTED op 0xffffffff81aaead8
    usecount 3, writecount 2, refcount 1 seqc users 0
    hold count flags ()
    flags (VV_VMSIZEVNLOCK|VI(0x40)|VMP_LAZYLIST)
    v_object 0xfffff803dac10c30 ref 2 pages 0 cleanbuf 0 dirtybuf 0
    lock type nfs: UNLOCKED
#0 0xffffffff80b990c8 at lockmgr_lock_flags+0x1b8
#1 0xffffffff80cc0f20 at vop_sigdefer+0x30
#2 0xffffffff81213a93 at VOP_LOCK1_APV+0x133
#3 0xffffffff80cfc96b at VOP_LOCK1+0x4b
#4 0xffffffff80cfa260 at _vn_lock+0x140
#5 0xffffffff80cf7902 at vn_truncate+0x82
#6 0xffffffff80c4febe at kern_ftruncate+0xee
#7 0xffffffff8113eaa9 at amd64_syscall+0x169
#8 0xffffffff8110d6db at fast_syscall_common+0xf8
	fileid 3 fsid 0x3a3a00ff01
panic: Wrong a_desc in vop_lock1(0xfffffe016a9e6940, 0xfffffe010008fa50)

log0657.txt

Properly initialize ap.gen.desc

Accumulated bug fixes after the Peter' testing.

I consider removing the nfs n_mtx and using the vnode interlock instead, as the future change.

Integrate delayed setsize locking into vn_lock() more tight, now that the code moved out from VOP.

It all looks good to me, although I won't claim to
understand all the required semantics in
vn_lock_delayed_setsize().

This revision is now accepted and ready to land.Mon, Mar 2, 10:30 PM
sys/fs/deadfs/dead_vnops.c
83

These VOPs are mostly alphabetically sorted, with the exception of vop_fplookup_*.

sys/kern/vfs_vnops.c
2007

This assertion is redundant. I don't understand why we check v_data == NULL at all.

2014

vn_clear_delayed_setsize_locked()?

2038

Shouldn't it be __predict_true?

This is an unlocked read, so maybe should be protected with atomic_load.

2045

Why not pass the arguments normally and let vn_lock_delayed_setsize() build the structure? This calling convention looks odd.

sys/sys/vnode.h
1256

It is strange that these helpers are called vn_delay_setsize* but the flag is VI_DELAYEDSSZ. IMO "delayed" is right, and the flag should be VI_DELAYED_SETSIZE or similar, it is not referenced often so does not need to be terse.

kib marked 5 inline comments as done.Fri, Mar 6, 12:23 AM

markj: sorry, I just committed before your notes come in, your suggested changes went into D55681

sys/kern/vfs_vnops.c
2007

This is similar to the VI_DOOMED check, but with some delicate differences. The vnode being reclaimed might drop the vnode lock in VOP_RECLAIM(), and there might be some pending operations that needs to be done on the vnode. For instance, the buffer flushes.

So checking the VI_DOOMED would not allow that operations to finish.