-
Notifications
You must be signed in to change notification settings - Fork 341
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
TestMemNodeFsWrite: content mismatch: got "", want "hello" #479
Comments
That should be impossible. st_size updates on each write. Also, memnodefs is completely in-memory, no? |
the file contents are backed by a normal filesystem. It is just the tree and metadata that are in-memory. |
This issue is still present as of today: GOMAXPROCS=1 go test -run TestMemNodeFsWrite -count 1000 -failfastgo version go1.21.13 linux/amd64
(neo) (zdev+py39.env) (g.env) kirr@deca:~/src/neo/src/github.com/hanwen/go-fuse/fuse/nodefs$ GOMAXPROCS=1 go test -run TestMemNodeFsWrite -count 1000 -failfast
--- FAIL: TestMemNodeFsWrite (0.00s)
memnode_test.go:67: content mismatch: got "", want "hello"
FAIL
exit status 1
FAIL github.com/hanwen/go-fuse/fuse/nodefs 1.275s go-fuse: @szmi I believe it to be a KERNEL REGRESSION introduced in 2021 by https://git.kernel.org/linus/fa5eee57e33e (Linux 5.16) which changed fuse_flush to invalidate only st_blocks, instead of all attributes, in particularly stopping to invalidate st_size. Please see #479 (comment) for full details. |
Hello everyone.
I'm hitting
TestMemNodeFsWrite
failure in tests. Even though this test lives in deprecated nodefs, it might be due to 2021 kernel regression which might be affecting whole go-fuse and other FUSE libraries. Please read below for details.The test fails reliably and quickly when run in a loop:
GOMAXPROCS=1 go test -run TestMemNodeFsWrite -count 1000 -failfast
Note: for this test to fail it experimentally turned out to be important for other fuse filesystems to be unmounted and
/sys/fs/fuse/connections
to be empty.Here is debug log of a failure:
This test(*) first writes
hello
into/test
file and then wants to read it back. The file is ultimately served by loopback filesystem, which delegates getattr, write and read to underlying os fs.The write happens in
rx 26 WRITE n3 {Fh 2 [0 +5) L 0 WRONLY,NONBLOCK,0x8000} "hello" 5b
. It goes ok. Then the kernel issuesGETATTR
request. This request - in this particular run - is probably issued because attributes happen to become timed out on the kernel side (attributes TTL in this test is 100ms). The getattr is served by loopbackfs by statting the underlying os file which still stats as with st_size=0. This seems to be correct behaviour since FLUSH was not yet called. Then the FLUSH is called - when file handle opened for writing is closed. Then the file is opened again for reading. This happens onrx 34: OPEN n3 {O_RDONLY,0x8000}
. The kernel does not send new GETATTR request to refresh its view of file size, and since previous getattr returnedst_size=0
the kernel serves all reads from its pagecache directly without querying the filesystem with any READ request. Which leads to failure since the file reads as empty instead ofhello
.There is no documentation for FUSE protocol anywhere (semantic of it, not messages serialization), but the bug seems to be due to that the kernel does not invoke GETATTR after FLUSH.
This behaviour was introduced in 2021 in https://git.kernel.org/linus/fa5eee57e33e (Linux 5.16) which changed
fuse_flush
to invalidate onlyst_blocks
, instead of all attributes, in particularly stopping to invalidatest_size
.Kirill
/cc @szmi, @Nikratio, @amir73il
(*)
go-fuse/fuse/nodefs/memnode_test.go
Lines 55 to 69 in 255ab74
go-fuse:
v2.3.0-11-g255ab74
os:
Linux deca 6.1.0-9-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.27-1 (2023-05-08) x86_64 GNU/Linux
go:
go version go1.20.5 linux/amd64
The text was updated successfully, but these errors were encountered: