Bug #14633

Updated by Andy Fiddaman 6 months ago

A user reported that trying to do a recursive `rm -rf` on a directory tree on a 9p mount in a Linux guest is failing. 

 A simple reproducer which fails under Fedora 35 and Ubuntu 21.10: 

 # mkdir -p aaaa/bbbb 
 # touch aaaa/bbbb/cccc 
 # rm -rf aaa 
 rm: cannot remove 'aaaa': File exists 

 It turns out that @rm@ in these modern Linux distributions is using @unlinkat()@, and this is failing on the 

 # strace rm -rf /a/aaaa 2>&1 | grep unlinkat 
 unlinkat(5, "cccc", 0)                    = -1 EINVAL (Invalid argument) 
 unlinkat(4, "bbbb", AT_REMOVEDIR)         = -1 EINVAL (Invalid argument) 
 unlinkat(AT_FDCWD, "/a/aaaa", AT_REMOVEDIR) = -1 EEXIST (File exists) 

 and the debug output from @lib9p@ 

 [DEBUG]    l9p_dispatch_request: Treaddir tag=0 fid=5 offset=0 count=8168 
 DEBUG]    l9p_dispatch_request: Twalk tag=0 fid=5 newfid=6 wname="cccc" 
 [DEBUG]    open_fid: authinfo 1290a50 now used by 6 
 [DEBUG]    l9p_dispatch_request: Tunlinkat tag=0 dirfd=5 name="cccc" flags=0x0 
 [DEBUG]    l9p_respond: Rlerror tag=0 errnum=22 (Invalid argument) 

 Tracing through, the EINVAL from the attempt to remove the file is because the code asserts 
 that the directory fid is not open, which it often is has to be for the unlinkat() call.