Re: Why does namei return an exclusively locked vnode when LOCKSHARED is specified?

From: Mark Johnston <markj_at_freebsd.org>
Date: Tue, 17 Dec 2024 19:27:38 UTC
On Tue, Dec 17, 2024 at 12:19:26PM -0700, Alan Somers wrote:
> According to namei(9), namei should return a shared lock when
> LOCKSHARED is specified.  But in my experiments, it always seems to
> return an exclusive lock instead.  For example:
> 
> $ cd /usr/tests/sys/fs/fusefs
> $ sudo dtrace -i 'fbt:fusefs:fuse_vnop_getattr:entry /pid==$target/
> {printf("islocked=%#x", args[0]->a_vp->v_vnlock->lk_lock); stack();}'
> -i 'fbt:kernel:vop_stdstat:entry /pid==$target/
> {printf("islocked=%#x", args[0]->a_vp->v_vnlock->lk_lock);}' -c
> "./getattr --gtest_filter=Getattr.attr_cache -v"
> [==========] Running 1 test from 1 test suite.
> [----------] Global test environment set-up.
> [----------] 1 test from Getattr
> [ RUN      ] Getattr.attr_cache
> INIT        ino= 0
> ACCESS      ino= 1 mask=0x1
> LOOKUP      ino= 1 some_file.txt
> GETATTR     ino=42
> [       OK ] Getattr.attr_cache (3 ms)
> [----------] 1 test from Getattr (3 ms total)
> 
> [----------] Global test environment tear-down
> [==========] 1 test from 1 test suite ran. (4 ms total)
> [  PASSED  ] 1 test.
> CPU     ID                    FUNCTION:NAME
>   3  19743                vop_stdstat:entry islocked=0x21
>   3  19743                vop_stdstat:entry islocked=0xfffff80004f16740
>   3  68298          fuse_vnop_getattr:entry islocked=0xfffff80004f16740
>               kernel`VOP_GETATTR_APV+0x90
>               kernel`vop_stdstat+0x147
>               kernel`VOP_STAT_APV+0x91
>               kernel`kern_statat+0x183
>               kernel`sys_fstatat+0x27
>               kernel`amd64_syscall+0x1af
>               kernel`0xffffffff8106cd5b
> 
>   3  19743                vop_stdstat:entry islocked=0xfffff80004f16740
>   3  68298          fuse_vnop_getattr:entry islocked=0xfffff80004f16740
>               kernel`VOP_GETATTR_APV+0x90
>               kernel`vop_stdstat+0x147
>               kernel`VOP_STAT_APV+0x91
>               kernel`kern_statat+0x183
>               kernel`sys_fstatat+0x27
>               kernel`amd64_syscall+0x1af
>               kernel`0xffffffff8106cd5b
> 
> dtrace: pid 3554 has exited
> 
> From that output, the first vop_stdstat is probably for the
> mountpoint, and isn't what I'm concerned about.  But the second two
> are for a fusefs file.  The LK_SHARE bit is not set, indicating an
> exclusive lock.  That's even though the call to namei in kern_statat
> specifies LOCKSHARED | LOCKLEAF.
> 
> What am I missing?

Having noticed the same phenomenon in p9fs and scratching my head for a
while: is fusefs failing to call VN_LOCK_ASHARE() in this case?  I see
that it's predicated on "data->dataflags & FSESS_ASYNC_READ", but I'm
not sure why - the comment seems to suggest a misunderstanding of what
VN_LOCK_ASHARE() does.

... oh, also perhaps because fusefs mounts don't set MNTK_LOOKUP_SHARED?