unexpected behavior on direct_io = True
I slightly modified example/hello.py, so that it uses direct_io, and I cannot explain the result. With ./test mountpoint, the command cat ./test/hello works fine with direct_io = False, but enters infinite loop when direct_io = True.
The interesting part: compare output of strace -y cat ./test/hello >/dev/null:
direct_io = False
openat(AT_FDCWD</home/mateusz/Downloads>, "./test/hello", O_RDONLY) = 3</home/mateusz/Downloads/test/hello>
newfstatat(3</home/mateusz/Downloads/test/hello>, "", {st_mode=S_IFREG|0444, st_size=1000, ...}, AT_EMPTY_PATH) = 0
fadvise64(3</home/mateusz/Downloads/test/hello>, 0, 0, POSIX_FADV_SEQUENTIAL) = 0
mmap(NULL, 139264, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f5bf4bdb000
read(3</home/mateusz/Downloads/test/hello>, "ffffffffffffffffffffffffffffffff"..., 131072) = 1000
write(1</dev/null>, "ffffffffffffffffffffffffffffffff"..., 1000) = 1000
read(3</home/mateusz/Downloads/test/hello>, "", 131072) = 0
munmap(0x7f5bf4bdb000, 139264) = 0
close(3</home/mateusz/Downloads/test/hello>) = 0
direct_io = True
openat(AT_FDCWD</home/mateusz/Downloads>, "./test/hello", O_RDONLY) = 3</home/mateusz/Downloads/test/hello>
newfstatat(3</home/mateusz/Downloads/test/hello>, "", {st_mode=S_IFREG|0444, st_size=1000, ...}, AT_EMPTY_PATH) = 0
fadvise64(3</home/mateusz/Downloads/test/hello>, 0, 0, POSIX_FADV_SEQUENTIAL) = 0
mmap(NULL, 139264, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f60baa38000
read(3</home/mateusz/Downloads/test/hello>, "ffffffffffffffffffffffffffffffff"..., 131072) = 131072
write(1</dev/null>, "ffffffffffffffffffffffffffffffff"..., 131072) = 131072
read(3</home/mateusz/Downloads/test/hello>, "ffffffffffffffffffffffffffffffff"..., 131072) = 131072
write(1</dev/null>, "ffffffffffffffffffffffffffffffff"..., 131072) = 131072
read(3</home/mateusz/Downloads/test/hello>, "ffffffffffffffffffffffffffffffff"..., 131072) = 131072
write(1</dev/null>, "ffffffffffffffffffffffffffffffff"..., 131072) = 131072
read(3</home/mateusz/Downloads/test/hello>, "ffffffffffffffffffffffffffffffff"..., 131072) = 131072
write(1</dev/null>, "ffffffffffffffffffffffffffffffff"..., 131072) = 131072
.... # infinite loop
Ubuntu 22.04
fusermount3 version: 3.10.5
Full reproducer: hello.py.txt
i think that the i found the behavior difference varying on direct_io switch state.
with direct_io = False, even if user-defined read() returns N bytes always, the framework traces number of bytes already passed to user, and seemingly will trim it to at most st.st_size and at some point will return less than N bytes.
with direct_io = True, the st.st_size value is not taken into consideration, so cat program enters infinite loop.
can someone with better insights tell if I described it correctly?
Speaking about documentation: it is mentioned in direct_io section:
This option disables the use of page cache (file content cache) in the kernel for this filesystem. This has several affects:
...
* The return value of the read() and write() system calls will correspond to the return values of the read and write operations. This is useful for example if the file size is not known in advance (before reading it).
I can tell however, that for someone like me, who uses FUSE first time, this is the confusing part. direct_io switch should be only about performance, and from interface point of view it shouldn't change the functionality. And if it does, I would expect to have a clear warning about that.
If however that "side-effect" is somehow obvious, please let me know - it might be just my lack of experience.