Page MenuHomeFreeBSD

fuse: Ensure fuse_internal_cache_attrs() is called with exclusive lock
AbandonedPublic

Authored by emil_etsalapatis.com on Mon, Feb 2, 12:22 AM.
Tags
None
Referenced Files
Unknown Object (File)
Wed, Feb 18, 7:28 AM
Unknown Object (File)
Mon, Feb 2, 4:12 PM
Unknown Object (File)
Mon, Feb 2, 2:54 PM
Unknown Object (File)
Mon, Feb 2, 10:38 AM
Unknown Object (File)
Mon, Feb 2, 8:27 AM
Unknown Object (File)
Mon, Feb 2, 8:08 AM
Unknown Object (File)
Mon, Feb 2, 7:02 AM
Subscribers

Details

Reviewers
asomers
Summary

The fuse_internal_cache_attrs() call modifies the vattr of the vnode along
with its cached metadata. These fields are supposed to be protected by the
vnode lock, but calling the function from fuse_internal_do_getattr() is
done only with shared locking, not exlcusive. Upgrade the vnode lock to
exclusive before updating its metadata.

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Passed
Unit
No Test Coverage
Build Status
Buildable 70333
Build 67216: arc lint + arc unit

Event Timeline

Thanks for working on this! I was actually working on the exact same problem myself last week. And I came up with a very similar solution. But then I realized that it wouldn't work :( . The cached attrs also need to be modified in paths where the vnode lock cannot be upgraded. So my plan is to add a mutex just to protect them. I started work on it last week. But now I'm on vacation, so I can't resume work for a few more days. But thanks for your interest in fuse.

Thanks for working on this! I was actually working on the exact same problem myself last week. And I came up with a very similar solution. But then I realized that it wouldn't work :( . The cached attrs also need to be modified in paths where the vnode lock cannot be upgraded. So my plan is to add a mutex just to protect them. I started work on it last week. But now I'm on vacation, so I can't resume work for a few more days. But thanks for your interest in fuse.

Makes sense! In case it helps, I found another place in FUSE with a similar problem - a normally read-only operation VFS operation requiring a lock upgrade to manage cached state - another one is when trying to execute a binary when the server sets the direct IO flag:

VNASSERT failed: locked not true at           
  /root/freebsd-src/sys/kern/vfs_subr.c:5816 (assert_vop_elocked)           
  0xfffffe02b7e70dc0: type VREG state VSTATE_CONSTRUCTED op                 
  0xffffffff85464720                                                        
      usecount 1, writecount -1, refcount 1 seqc users 0                    
      hold count flags ()                                                   
      flags ()                                                              
      v_object 0xfffffe02b48b81e0 ref 0 pages 0 cleanbuf 0 dirtybuf 0       
      lock type fuse: SHARED (count 1)                                      
  nodeid: 4121, parent nodeid: 0, nlookup: 2, flag: 0x200                   
  panic: fuse_filehandle_init: vnode is not exclusive locked but should be  
  cpuid = 2                                                                 
  time = 1769988829                                                         
  KDB: stack backtrace:                                                     
  db_trace_self_wrapper() at 0xffffffff805b4145 =                           
  db_trace_self_wrapper+0xa5/frame 0xfffffe02ace54af0                       
  kdb_backtrace() at 0xffffffff812f2746 = kdb_backtrace+0xc6/frame          
  0xfffffe02ace54c50                                                        
  vpanic() at 0xffffffff81242f64 = vpanic+0x214/frame 0xfffffe02ace54df0    
  panic() at 0xffffffff81242d45 = panic+0xb5/frame 0xfffffe02ace54eb0       
  assert_vop_elocked() at 0xffffffff8142d56c =                              
  assert_vop_elocked+0x14c/frame 0xfffffe02ace54f60                         
  fuse_filehandle_init() at 0xffffffff8543f7ce =                            
  fuse_filehandle_init+0x22e/frame 0xfffffe02ace54fd0                       
  fuse_filehandle_open() at 0xffffffff8543f480 =                            
  fuse_filehandle_open+0x2c0/frame 0xfffffe02ace550f0                       
  VOP_OPEN_APV() at 0xffffffff81d66c35 = VOP_OPEN_APV+0xf5/frame            
  0xfffffe02ace55150                                                        
  exec_check_permissions() at 0xffffffff811acc9d =                          
  exec_check_permissions+0x4ed/frame 0xfffffe02ace55310                     
  kern_execve() at 0xffffffff811a854b = kern_execve+0xe8b/frame             
  0xfffffe02ace55bd0                                                        
  sys_execve() at 0xffffffff811a6ffa = sys_execve+0x12a/frame               
  0xfffffe02ace55d10                                                        
  amd64_syscall() at 0xffffffff81bf0611 = amd64_syscall+0x481/frame         
  0xfffffe02ace55f30                                                        
  fast_syscall_common() at 0xffffffff81ba7bdb =                             
  fast_syscall_common+0xf8/frame 0xfffffe02ace55f30                         
  --- syscall (59, FreeBSD ELF64, execve), rip = 0x20b9f6e6cd6a, rsp =      
  0x20b9f3d1f298, rbp = 0x20b9f3d1f3e0 ---                                  
  KDB: enter: panic

FWIW a dedicated mutex for the cached attrs sounds great. I will abandon this diff since you are looking into this :)