As in our example for passthrough, READ operation is not implemented since kernel should handle all of them directly on the backing file instead. But turns out kernel can still send READ requests to us after we reply OPEN request by opened_passthrough in some cases, namely on readahead(2).
Here is the C code to trigger that.
#define _GNU_SOURCE
#include <assert.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
int main() {
int f = open("/path/to/fuse/mnt/passthrough", O_RDONLY | O_CLOEXEC);
assert(f >= 0);
readahead(f, 0, 4096);
}
Running the passthrough example FUSE with:
cargo build --example passthrough && sudo RUST_LOG=debug ./target/debug/examples/passthrough /path/to/fuse/mnt
Then compile and run the C code above. We'll get some logs from the FUSE daemon:
[2026-05-03T18:25:11Z DEBUG fuser::request] FUSE( 30) ino 0x0000000000000001 LOOKUP name "passthrough" thread=fuser-0
[2026-05-03T18:25:11Z DEBUG fuser::request] FUSE( 32) ino 0x0000000000000002 OPEN flags 0x8000 thread=fuser-0
MISS! new BackingId { channel: (Weak), backing_id: 4 }
-> opened_passthrough(4, 0, BackingId { channel: (Weak), backing_id: 4 });
[2026-05-03T18:25:11Z DEBUG fuser::request] FUSE( 34) ino 0x0000000000000002 READ fh FileHandle(4), offset Ok(0), size 4096 thread=fuser-0
[2026-05-03T18:25:11Z WARN fuser] [Not Implemented] read(ino: INodeNo(
0x2,
), fh: 4, offset: 0, size: 4096, flags: OpenFlags(
0x8000,
), lock_owner: None)
[2026-05-03T18:25:11Z DEBUG fuser::request] FUSE( 36) ino 0x0000000000000002 RELEASE fh FileHandle(4), flags 0x8000, flush false, lock owner None thread=fuser-0
Put fh 4
Put fh 4, was BackingId { channel: (Weak), backing_id: 4 }
If we want to correctly handle this, there should still be a fallback path for READ requests, and file descriptors are required to be kept open. This makes code much more complicated and results in readahead slowing down the performance, which seems wrong to me...
Or probably it is the kernel to be blamed in this case?
EDIT: My kernel version is 6.18.24
As in our example for
passthrough,READoperation is not implemented since kernel should handle all of them directly on the backing file instead. But turns out kernel can still sendREADrequests to us after we replyOPENrequest byopened_passthroughin some cases, namely onreadahead(2).Here is the C code to trigger that.
Running the passthrough example FUSE with:
cargo build --example passthrough && sudo RUST_LOG=debug ./target/debug/examples/passthrough /path/to/fuse/mntThen compile and run the C code above. We'll get some logs from the FUSE daemon:
If we want to correctly handle this, there should still be a fallback path for READ requests, and file descriptors are required to be kept open. This makes code much more complicated and results in
readaheadslowing down the performance, which seems wrong to me...Or probably it is the kernel to be blamed in this case?
EDIT: My kernel version is 6.18.24