FUSE - 避免在 GetAttr 中计算大小
Posted
技术标签:
【中文标题】FUSE - 避免在 GetAttr 中计算大小【英文标题】:FUSE - avoid calculating size in GetAttr 【发布时间】:2018-02-26 07:44:25 【问题描述】:我正在为远程服务实现 FUSE 文件系统。
当用户打开文件时,我会进行网络调用以获取文件的内容。 It appears 必须通过 GetAttr
报告文件的大小才能打开工作。
为了知道文件的大小,我必须发出网络调用,并且由于在执行ls
时每个条目都会调用GetAttr
,所以我担心这种设计(如果用户在目录中执行ls
有很多项目,它必须获取所有文件,即使用户不想打开其中任何一个)。
我该如何解决这个问题?我的想法是:
使用不依赖于报告大小的较低级别的读取方法?我认为使用Read
而不是 Open
会有所帮助,但是如果没有尺寸,我就无法使用它。
如果我能将来自Open
的GetAttr
呼叫与其他呼叫(包括ls
)区分开来,我可以仅在需要时发出网络呼叫。
我使用 Go 和 go-fuse,但我认为这无关紧要,因为这是一个通用的 FUSE 问题。
此外,FUSE 文档是非常少的(实际上是缺失的)文档。如果熟悉此事的人能解释一下ls
、cd
和cat
的调用流程,那就太好了——按什么顺序调用 FUSE 函数。
比如为什么会有Open
和Read
。
更新: 我一直在浏览 SSHFS,它被认为是 FUSE 文件系统的规范示例,它似乎也可以通过网络在 getattr 上获取文件:https://github.com/libfuse/sshfs/blob/master/sshfs.c#L3167 你怎么看?
【问题讨论】:
【参考方案1】:您看到的问题是因为内核正在缓冲您的读取,并且当它这样做时,它使用 inode 的大小来准确计算它必须复制到用户空间的字节数 (https://elixir.bootlin.com/linux/v4.19.7/source/mm/filemap.c#L2137)。所以有不同的解决方法:
从 GetAttr 返回巨大的 st_size
当您打开文件时,设置 direct_io 标志,这样您就不会使用页面缓存。
【讨论】:
【参考方案2】:我不知道 go-fuse 的 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
中,首先从网络中读取数据,如果到达文件末尾,则在return 0
中读取return 0
。
当我编写文件系统时,这个doc 对我帮助很大。
【讨论】:
将文件大小设置为零会使某些程序感到困惑,以至于它们甚至不会尝试读取文件。以上是关于FUSE - 避免在 GetAttr 中计算大小的主要内容,如果未能解决你的问题,请参考以下文章