Page MenuHomeFreeBSD

ddb show lockedvnods: avoid trap for ufs vnode under construction
ClosedPublic

Authored by rlibby on Tue, Sep 30, 7:21 AM.
Tags
None
Referenced Files
F132503448: D52795.diff
Fri, Oct 17, 11:24 AM
F132395636: D52795.diff
Thu, Oct 16, 1:40 PM
Unknown Object (File)
Sun, Oct 12, 3:54 PM
Unknown Object (File)
Sat, Oct 11, 3:35 PM
Unknown Object (File)
Thu, Oct 9, 2:12 PM
Unknown Object (File)
Thu, Oct 9, 2:12 PM
Unknown Object (File)
Thu, Oct 9, 2:11 PM
Unknown Object (File)
Thu, Oct 9, 2:11 PM
Subscribers

Details

Summary

ddb show lockedvnods might find a ufs vnode after it is inserted into
the mount queue in ffs_vgetf but before the dinode is allocated. Avoid
trapping by testing for the dinode pointer.

Sponsored by: Dell Inc.

Test Plan

Manual testing of ddb show lockedvnods no longer traps with ufs vnodes under construction.

# jot 0 | xargs -P10 -I %% sh -c "touch %%; rm %%" &
# dtrace -w -n 'fbt::vfs_hash_insert:entry {chill(100000000)}'
# sysctl debug.kdb.enter=1
debug.kdb.enter:KDB: enter: sysctl debug.kdb.enter
[ thread pid 46169 tid 100285 ]
Stopped at      kdb_sysctl_enter+0x95:  movq    $0,0x121ca00(%rip)
db> show lockedvnods
Locked vnodes
vnode 0xfffff8000685a528: type VDIR state VSTATE_CONSTRUCTED op 0xffffffff81b444b8
    usecount 1, writecount 0, refcount 4 seqc users 0 mountedhere 0
    hold count flags ()
    flags (VMP_LAZYLIST)
    v_object 0xfffff8000b622e88 ref 0 pages 6 cleanbuf 0 dirtybuf 1
    lock type ufs: SHARED (count 1)
	nlink=500, effnlink=496, size=22528, extsize=0
	generation=f5e62862, uid=0, gid=0, flags=0x0
	ino 1685376, on dev gpt/rootfs
vnode 0xfffff800067cc898: type VDIR state VSTATE_CONSTRUCTED op 0xffffffff81b444b8
    usecount 11, writecount 0, refcount 4 seqc users 1 mountedhere 0
    hold count flags ()
    flags (VMP_LAZYLIST)
    v_object 0xfffff8000b6a01f0 ref 0 pages 1 cleanbuf 0 dirtybuf 1
    lock type ufs: EXCL by thread 0xfffff80102ee4780 (pid 46167, touch, tid 100213)
 with exclusive waiters pending
 with shared waiters pending
	nlink=2, effnlink=2, size=512, extsize=0
	generation=1f74e18d, uid=1000, gid=0, flags=0x0
	ino 3157375, on dev gpt/rootfs
vnode 0xfffff80171390528: type VNON state VSTATE_UNINITIALIZED op 0xffffffff81b444b8
    usecount 1, writecount 0, refcount 1 seqc users 0
    hold count flags ()
    flags ()
    lock type ufs: EXCL by thread 0xfffff80102ee4780 (pid 46167, touch, tid 100213)
	nlink=0, effnlink=0, size=0, dinode=NULL (fields omitted)
	generation=0, uid=0, gid=0, flags=0x0
	ino 3157390, on dev gpt/rootfs
db>

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Not Applicable
Unit
Tests Not Applicable

Event Timeline

rlibby added reviewers: mckusick, markj.

maybe print that the pointer is NULL?

In D52795#1206234, @mjg wrote:

maybe print that the pointer is NULL?

Do you mean to make it obvious that something is being omitted?

In the case that I looked at, it's obvious that it's "under construction" due to the type still being VNON and state still being VSTATE_UNINITIALIZED, but yes we could also print something more explicit.

# jot 0 | xargs -P10 -I %% sh -c "touch %%; rm %%" &
# dtrace -w -n 'fbt::vfs_hash_insert:entry {chill(100000000)}' &
# sysctl debug.kdb.enter=1
Kdebug.kdb.enter:DB: enter: sysctl debug.kdb.enter
[ thread pid 31561 tid 100249 ]
Stopped at      kdb_sysctl_enter+0x95:  movq    $0,0x121cef0(%rip)
db> show lockedvnods
Locked vnodes
vnode 0xfffff802ea339898: type VDIR state VSTATE_CONSTRUCTED op 0xffffffff81b444b8
    usecount 11, writecount 0, refcount 4 seqc users 1 mountedhere 0
    hold count flags ()
    flags (VMP_LAZYLIST)
    v_object 0xfffff80292e2a7c0 ref 0 pages 1 cleanbuf 0 dirtybuf 1
    lock type ufs: EXCL by thread 0xfffff8000a5fd780 (pid 31549, touch, tid 100231)
 with exclusive waiters pending
 with shared waiters pending
	nlink=2, effnlink=2, size=512, extsize 0
	generation=1f74e18d, uid=1000, gid=0, flags=0x0
	ino 3157375, on dev gpt/rootfs
vnode 0xfffff802582aedc0: type VNON state VSTATE_UNINITIALIZED op 0xffffffff81b444b8
    usecount 1, writecount 0, refcount 1 seqc users 0
    hold count flags ()
    flags ()
    lock type ufs: EXCL by thread 0xfffff8000a5fd780 (pid 31549, touch, tid 100231)
	nlink=0, effnlink=0, size=0
	generation=0, uid=0, gid=0, flags=0x0
	ino 3157386, on dev gpt/rootfs
db> c
 0 -> 0

Is the current output clear enough or do you want to see something like dinode=NULL?

The above may be true and the pointer may be populated depending on when you got the the inode. I would just add something like "->i_din2 is NULL, some information omitted" or compatible.

Sure, I'm ambivalent, I just wanted to fix the trap. I'll prepare the patch.

To be clear though I think this is the vget sequence in current code:

  • inode allocated
  • vnode inserted into mount queue
  • --- window for trap ---
  • dinode allocated
  • vtype set

And on the vgone/reclaim side, in ufs_reclaim v_data is cleared before the dinode is freed.

In other words, I think this construction race is the only time we'll see this and the type and state will be as above.

Alternately, we could fib and do

printf(", extsize=%d", ip->i_din2 != NULL ? ip->i_din2->di_extsize : 0);

I think this is turning into a bikeshed, so just do what you feel.

mjg feedback: indicate when i_din2 is NULL

This revision is now accepted and ready to land.Wed, Oct 1, 10:30 AM