Closed rfjakob closed 4 years ago
By the way, the good news is that tests 002 to 034 pass! (or are skipped because they need a block device)
your explanation sounds plausible, but I can't repro.
func TestOpenDirFStat(t *testing.T) { tc := NewTestCase(t) defer tc.Cleanup()
if err := os.Mkdir(tc.origSubdir, 0777); err != nil {
t.Fatalf("Mkdir failed: %v", err)
}
fd, err := syscall.Open(tc.mountSubdir, syscall.O_RDONLY, 0755);
if err != nil {
t.Fatalf("Open(%q): %v", tc.mountSubdir, err)
}
defer syscall.Close(int(fd))
if err := os.Rename(tc.mountSubdir, tc.mountSubdir + ".renamed"); err != nil {
t.Fatalf("rename(%q): %v", tc.mountSubdir, err)
}
var result syscall.Stat_t
if err := syscall.Fstat(int(fd), &result); err != nil {
t.Fatalf("dir.stat after rename: %v", err)
}
}
gives me
$ go test -v -run OpenDirFStat === RUN TestOpenDirFStat 2015/09/24 11:13:31 Dispatch: INIT, NodeId: 0. data: _fuse.InitIn: {7.23 Ra 0x20000 SPLICE_WRITE,POSIX_LOCKS,EXPORT_SUPPORT,BIG_WRITES,DONT_MASK,SPLICE_READ,ASYNC_READ,ATOMIC_O_TRUNC,READDIRPLUS_AUTO,SPLICE_MOVE,FLOCK_LOCKS,AUTO_INVAL_DATA,READDIRPLUS,0x38000} 2015/09/24 11:13:31 Serialize: INIT code: OK value: {7.21 Ra 0x20000 AUTO_INVAL_DATA,READDIRPLUS,BIG_WRITES,ASYNC_READ 0/0 Wr 0x10000} 2015/09/24 11:13:31 Dispatch: ACCESS, NodeId: 1. data: {r} 2015/09/24 11:13:31 Serialize: ACCESS code: OK value: 2015/09/24 11:13:31 Dispatch: LOOKUP, NodeId: 1. names: [.Trash] 7 bytes 2015/09/24 11:13:31 Serialize: LOOKUP code: 2=no such file or directory value: {0 G0 E0.000000000 A0.000000000 {M00 SZ=0 L=0 0:0 B0_0 i0:0 A 0.000000000 M 0.000000000 C 0.000000000}} 2015/09/24 11:13:31 Dispatch: LOOKUP, NodeId: 1. names: [.Trash-1000] 12 bytes 2015/09/24 11:13:31 Serialize: LOOKUP code: 2=no such file or directory value: {0 G0 E0.000000000 A0.000000000 {M00 SZ=0 L=0 0:0 B0_0 i0:0 A 0.000000000 M 0.000000000 C 0.000000000}} 2015/09/24 11:13:31 Dispatch: LOOKUP, NodeId: 1. names: [subdir] 7 bytes 2015/09/24 11:13:31 Serialize: LOOKUP code: OK value: {3 G0 E0.100000000 A0.100000000 {M040777 SZ=40 L=2 1000:1000 B0_4096 i0:3 A 1443086011.450558775 M 1443086011.450558775 C 1443086011.450558775}} 2015/09/24 11:13:31 Dispatch: OPENDIR, NodeId: 3. 2015/09/24 11:13:31 Serialize: OPENDIR code: OK value: {Fh 2 } 2015/09/24 11:13:31 Dispatch: LOOKUP, NodeId: 1. names: [subdir.renamed] 15 bytes 2015/09/24 11:13:31 Serialize: LOOKUP code: 2=no such file or directory value: {0 G0 E0.000000000 A0.000000000 {M00 SZ=0 L=0 0:0 B0_0 i0:0 A 0.000000000 M 0.000000000 C 0.000000000}} 2015/09/24 11:13:31 Dispatch: RENAME, NodeId: 1. data: {1} names: [subdir subdir.renamed] 22 bytes 2015/09/24 11:13:31 Serialize: RENAME code: OK value: 2015/09/24 11:13:31 Dispatch: GETATTR, NodeId: 3. data: {Fh 0} 2015/09/24 11:13:31 Serialize: GETATTR code: OK value: {A0.100000000 {M040777 SZ=40 L=2 1000:1000 B0_4096 i0:3 A 1443086011.451558799 M 1443086011.450558775 C 1443086011.451558799}} 2015/09/24 11:13:31 Dispatch: RELEASEDIR, NodeId: 3. data: {Fh 2 0x8000 L0} 2015/09/24 11:13:31 Serialize: RELEASEDIR code: OK value: 2015/09/24 11:13:31 Dispatch: BATCH_FORGET, NodeId: 0. data: {2} 32 bytes --- PASS: TestOpenDirFStat (0.02s) PASS ok github.com/hanwen/go-fuse/fuse/test 0.024s
as you can see, the kernel sends the inode correctly, so the fstat succeeds.
Interesting. This is what the test does: https://github.com/rfjakob/fuse-xfstests/blob/gocryptfs/src/t_rename_overwrite.c I cannot check right now, but I believe I can repro this every time using t_rename_overwrite.c . Will check again tonight.
I think your test is missing the second directory - t_rename_overwrite.c
overwrites a directory with another directory.
This is what I get using t_rename_overwrite.c :
2015/09/24 21:45:18 Dispatch: LOOKUP, NodeId: 1. names: [dir2] 5 bytes
2015/09/24 21:45:18 Serialize: LOOKUP code: OK value: {3 G0 E1.000000000 A1.000000000 {M040775 SZ=4096 L=2 1026:1026 B8*4096 i0:3 A 1443123875.118179028 M 1443123875.118179028 C 1443123887.105220165}}
2015/09/24 21:45:18 Dispatch: OPENDIR, NodeId: 3.
2015/09/24 21:45:18 Serialize: OPENDIR code: OK value: {Fh 2 }
2015/09/24 21:45:18 Dispatch: LOOKUP, NodeId: 1. names: [dir1] 5 bytes
2015/09/24 21:45:18 Serialize: LOOKUP code: OK value: {4 G0 E1.000000000 A1.000000000 {M040775 SZ=4096 L=2 1026:1026 B8*4096 i0:4 A 1443123904.606280228 M 1443123904.606280228 C 1443123904.606280228}}
2015/09/24 21:45:18 Dispatch: RENAME, NodeId: 1. data: {1} names: [dir1 dir2] 10 bytes
2015/09/24 21:45:18 Serialize: RENAME code: OK value:
2015/09/24 21:45:18 Dispatch: GETATTR, NodeId: 3. data: {Fh 0}
2015/09/24 21:45:18 Serialize: GETATTR code: 2=no such file or directory value: {A0.000000000 {M00 SZ=0 L=0 0:0 B0*0 i0:0 A 0.000000000 M 0.000000000 C 0.000000000}}
2015/09/24 21:45:18 Dispatch: RELEASEDIR, NodeId: 3. data: {Fh 2 0x8000 L0}
2015/09/24 21:45:18 Serialize: RELEASEDIR code: OK value:
2015/09/24 21:45:18 Dispatch: FORGET, NodeId: 3. data: {1}
t_rename_overwrite: fstat(3): No such file or directory
I can reproduce this every time.
interesting. I didn't know rename for a directory could have an empty directory as target.
so, note that fstat doesnt have Fh set, but IIRC that also holds for non-directory fstat. I'll have a look to see if I can so something.
Yes, you can also do that using mv
:
mkdir a otherdir otherdir/a mv otherdir/a .
mv dir1 dir2 actually executes
rename("dir1", "dir2/dir1")
but I can repro the problem now.
Yes exactly, that's why you need "otherdir"
If this is difficult to fix, maybe we can get away with documenting it as a known limitation and leave it as is. It seems to be important enough to get its own xfstest, but I can't think of a use case that would break.
Note: xfstests generic/035 still fails, because the fstat cannot succeed
loopbackfs (actually, anything that implements the nodefs API) fails xfstests generic/035.
What this test does is simple:
This fails because unlike handles that point to files, handles that point to directories are not kept open until the user closes them.
nodefs.OpenDir() should work like Open() and pass the file handle up.