我正在为远程服务实现FUSE文件系统。
当用户打开文件时,我会进行网络调用以获取文件的内容。 It appears必须通过GetAttr
报告文件的大小才能开放工作
为了知道文件的大小,我必须发出网络调用,并且在执行GetAttr
时为每个条目调用ls
,我关心这个设计(如果用户ls
Read
1}}在一个包含很多项目的目录中,它必须获取所有文件,即使用户不想打开它们中的任何一个。)
我该如何解决这个问题?我的想法是:
Open
代替GetAttr
可以提供帮助,但是如果没有尺寸我就无法工作。Open
来自ls
的{{1}}来自其他来电(包括ls
),我只能在需要时发出网络电话。我使用Go和go-fuse,但我认为这不重要,因为它是一个普遍的FUSE问题。
此外,FUSE文档非常小(实际上缺少)文档。如果熟悉这个问题的人可以解释cd
,cat
和Open
的呼叫流程,那将是很好的 - 以哪种顺序调用FUSE函数。
例如,为什么同时存在Read
和{{1}}。
更新
我一直在浏览SSHFS,它被认为是FUSE文件系统的典型示例,它似乎也通过getattr上的网络获取文件:https://github.com/libfuse/sshfs/blob/master/sshfs.c#L3167
你觉得怎么样?
答案 0 :(得分:0)
您看到的问题是因为内核正在缓冲您的读取,并且在这样做时,它使用inode的大小来精确计算它必须复制到用户空间的字节数(https://elixir.bootlin.com/linux/v4.19.7/source/mm/filemap.c#L2137) 。因此,有不同的解决方法:
从GetAttr返回巨大的st_size
打开文件时,请设置direct_io标志,以免使用页面缓存。
答案 1 :(得分:0)
我不知道助焊剂的API。下面的信息基于libfuse的API。
SSHFS的GetAttr是在函数sshfs_getattr
中实现的,它看起来像发送网络请求获取文件大小信息。
运行cd
时,它将运行.access
回调以检查目录是否存在。
运行ls
时,它将首先调用.readdir
回调获取目录信息,然后调用.getattr
获取该目录中文件的信息。
运行cat
时,它将首先调用.getattr
获取文件信息和路径信息。然后调用.open
=> .read
=> .release
。
FUSE缺少文档,您最好先编写一个示例,然后可以在这些回调中添加一些printf
以获取一些信息。
.open
中,您可以创建一个私有数据并将其设置为fuse_file_info::fh
。此fuse_file_info::fh
可在以后的.read
回调中使用。.getattr
回调中将所有大小信息设置为零。然后在.open
中,将fuse_file_info::direct_io
设置为1。在.read
中,首先从网络读取数据,如果到达文件末尾,则在{{1}中访问return 0
}。当我编写文件系统时,此doc对我有很大帮助。