ILD

fuse direct io mode
作者:Yuan Jianpeng 邮箱:yuanjp89@163.com
发布时间:2025-2-12 站点:Inside Linux Development

使用fuse实现一个控制接口文件,先写入命令,然后读取结果。读取的时候发现一直返回0。


控制命令如下:

1
2
3
4
5
fd = open(NAS_MNT "/album/control", O_RDWR);
write(fd, "reload\n", 7);
lseek(fd, 0, SEEK_SET);
ret = read(fd, buf, sizeof(buf)-1);
close(fd);


结果read总是返回0。


经过一番分析,发现跟fuse的io mode有关系【1】。fuse有2种模式:


1 direct io模式

direct io模式会完全bypass掉page cache。读写请求会直接发给fuse程序。此时shared map默认会关掉。


2 cached模式

有 write-through 和 write-back两种。默认是write-through模式。

cached mode 读会从page cache满足。写跟上述两种子模式有关。

write-through会直接写到fuse 程序。write-back会先写到page cache。


fuse默认是write-through cached mode。所以,在读的时候,会:

[  127679.2808] FUSE: lookup ino 1 name control

[  127679.2809] RPLY: lookup ino 1 name control return ino 2

[  127679.2809] FUSE: open fh 1 ino 2 flags RDWR

[  127679.2810] RPLY: open fh 1 ino 2

[  127679.2811] FUSE: write fh 1 ino 2 size 7 off 0

[  127679.2835] RPLY: write fh 1 ino 2 done 7

[  127679.2836] FUSE: getattr fh 1 ino 2

[  127679.2837] RPLY: getattr fh 1 ino 2

[  127679.2837] FUSE: read fh 1 ino 2 size 4096 off 0

[  127679.2837] RPLY: read fh 1 ino 2 len 16

[  127679.2839] FUSE: flush fh 1 ino 2

[  127679.2839] RPLY: flush fh 1 ino 2

[  127679.2839] FUSE: release fh 1 ino 2

[  127679.2840] RPLY: release fh 1 ino 2


可以看到 read之前有一个getattr请求,这个接口返回的文件大小是0。导致内核构建的page cache大小是0,即使read返回了16个字节。

getattr返回一个大的长度后,read可以读取到数据。


但是我们开启direct io后。

[  127816.9747] FUSE: getattr ino 1

[  127816.9748] RPLY: getattr ino 1

[  127816.9749] FUSE: lookup ino 1 name control

[  127816.9749] RPLY: lookup ino 1 name control return ino 2

[  127816.9750] FUSE: open fh 1 ino 2 flags RDWR

[  127816.9751] RPLY: open fh 1 ino 2 direct io

[  127816.9751] FUSE: write fh 1 ino 2 size 7 off 0

[  127816.9778] RPLY: write fh 1 ino 2 done 7

[  127816.9780] FUSE: read fh 1 ino 2 size 127 off 0

[  127816.9780] RPLY: read fh 1 ino 2 len 16

[  127816.9781] FUSE: flush fh 1 ino 2

[  127816.9781] RPLY: flush fh 1 ino 2

[  127816.9781] FUSE: release fh 1 ino 2

[  127816.9782] RPLY: release fh 1 ino 2


fuse没有使用getattr来获取文件信息。read请求直接跳过了page cache。此时用户可以读取到内容。


开启direct io的方法,是在open的时候,回复FOPEN_DIRECT_IO标志。


libfuse只要设置

    struct fuse_file_info *fi

    fi.direct_io = 1

即可。

参考

https://docs.kernel.org/filesystems/fuse-io.html


Copyright © linuxdev.cc 2017-2024. Some Rights Reserved.