Skip to content

unexpected behavior on direct_io = True #64

Open

Description

@bieganski

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:

  1. 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
  1. 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

Activity

  1. bieganski commented on Feb 26, 2024

    @bieganski
    Author

    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?

  2. bieganski commented on Feb 26, 2024

    @bieganski
    Author

    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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions