FUSE - 避免在GetAttr中计算大小

时间:2017-09-17 19:20:08

标签: go fuse

我正在为远程服务实现FUSE文件系统。 当用户打开文件时,我会进行网络调用以获取文件的内容。 It appears必须通过GetAttr报告文件的大小才能开放工作 为了知道文件的大小,我必须发出网络调用,并且在执行GetAttr时为每个条目调用ls,我关心这个设计(如果用户ls Read 1}}在一个包含很多项目的目录中,它必须获取所有文件,即使用户不想打开它们中的任何一个。)

我该如何解决这个问题?我的想法是:

  • 使用较低级别的方法进行阅读,而不依赖于报告的大小?我认为使用Open代替GetAttr可以提供帮助,但是如果没有尺寸我就无法工作。
  • 如果我可以区分Open来自ls的{​​{1}}来自其他来电(包括ls),我只能在需要时发出网络电话。

我使用Go和go-fuse,但我认为这不重要,因为它是一个普遍的FUSE问题。

此外,FUSE文档非常小(实际上缺少)文档。如果熟悉这个问题的人可以解释cdcatOpen的呼叫流程,那将是很好的 - 以哪种顺序调用FUSE函数。
例如,为什么同时存在Read和{{1}}。

更新
我一直在浏览SSHFS,它被认为是FUSE文件系统的典型示例,它似乎也通过getattr上的网络获取文件:https://github.com/libfuse/sshfs/blob/master/sshfs.c#L3167
你觉得怎么样?

2 个答案:

答案 0 :(得分:0)

您看到的问题是因为内核正在缓冲您的读取,并且在这样做时,它使用inode的大小来精确计算它必须复制到用户空间的字节数(https://elixir.bootlin.com/linux/v4.19.7/source/mm/filemap.c#L2137) 。因此,有不同的解决方法:

  1. 从GetAttr返回巨大的st_size

  2. 打开文件时,请设置direct_io标志,以免使用页面缓存。

答案 1 :(得分:0)

我不知道助焊剂的API。下面的信息基于libfuse的API。

SSHFS的GetAttr是在函数sshfs_getattr中实现的,它看起来像发送网络请求获取文件大小信息。

运行cd时,它将运行.access回调以检查目录是否存在。

运行ls时,它将首先调用.readdir回调获取目录信息,然后调用.getattr获取该目录中文件的信息。

运行cat时,它将首先调用.getattr获取文件信息和路径信息。然后调用.open => .read => .release

FUSE缺少文档,您最好先编写一个示例,然后可以在这些回调中添加一些printf以获取一些信息。

  1. .open中,您可以创建一个私有数据并将其设置为fuse_file_info::fh。此fuse_file_info::fh可在以后的.read回调中使用。
  2. 您可以在.getattr回调中将所有大小信息设置为零。然后在.open中,将fuse_file_info::direct_io设置为1。在.read中,首先从网络读取数据,如果到达文件末尾,则在{{1}中访问return 0 }。

当我编写文件系统时,此doc对我有很大帮助。