LWN:重新思考fsinfo()

关注了就能看到更多这么棒的文章哦~

Rethinking fsinfo()

By Jonathan Corbet
August 21, 2020
原文来自:https://lwn.net/Articles/829212/
DeepL assisted translation

开发者们提出了 fsinfo()这个系统调用,它可以返回关于已经 mount 的文件系统的扩展信息(extended information),一年多前,我们在 LWN(https://lwn.net/Articles/792628,中文版在这里LWN:Linux讨论新加syscall (clone3, fchmodat4, fsinfo))首次对其进行了介绍。在这一年里,fsinfo()的形式没有太大变化,但关于是否合并的争论仍在继续。对一些人来说,fsinfo()是必需的,可以高效获取文件系统信息;对另一些人来说,它是一个不必要的、过度设计的机制。如果这个功能要进入 mainline kernel 的话,很可能需要进行修改。 

Linux 长期以来一直支持 statfs()系统调用(从用户空间通常见到的是 statvfs())作为获取已挂载文件系统信息的一种方式。不过,就像很常见的设计实现方式一样,statfs()的设计者列出了他们认为人们可能感兴趣的那些文件系统属性,限制这个系统调用只能获取这些属性,没有办法增加新的属性来扩展这个系统调用。不过,在 statfs()定型后的几十年里,文件系统设计者们不肯停止设计新的功能,所以现在有很多有用的信息无法从 statfs()中获得。这些细节包括挂载选项(mount options)、时间戳粒度(timestamp granularity)、相关标签(associated labels)和 UUID,以及文件系统是否支持扩展属性(extended attributes)、访问控制列表(access-control lists)和大小写不敏感查找(case-insensitive lookups)等功能。

恰好,内核现在通过/proc/mounts 虚拟文件提供了很多信息。除了缺失一部分信息之外,/proc/mounts 还有个缺点在于它的访问效率很低。读取该文件的内容需要 kernel 查询每一个已挂载的文件系统的相关信息,如果系统已经挂载很多文件系统的话,这个操作可能会变得开销很大。特别是运行容器化工作的系统中,可能有大量文件系统 mount 上来,某些情况下可能有数千个,所以读取/proc/mounts 确实很痛苦。也给大家普及一下这个知识:要想了解当前内核下新近挂载的文件系统的唯一方法,就是轮询/proc/mounts 并查找是否有新的条目。

David Howells 提出,用新的通知机制来解决轮询问题,但这个机制又依赖于 fsinfo(),fsinfo()的第 21 次修订版于 8 月 3 日发布。Howells 希望能在 5.9 合并窗口期间,将 notifications 和 fsinfo()这两个功能都合入 mainline,可是他并没有如愿。相反,这个请求导致了关于 fsinfo()当前形式是否合理的又一次讨论。

fsinfo()

fsinfo()的 API 设计时保证了全面性、可扩展性。将来应该永远不需要 fsinfo2()来添加新的属性。但这个 API 也很复杂。表面上看,这个接口是这样的:

int fsinfo(int dfd, const char *pathname, const struct fsinfo_params *params,
     size_t params_size, void *result_buffer, size_t result_buf_size);

int fsinfo(int dfd, const char *pathname, const struct fsinfo_params *params, size_t params_size, void *result_buffer, size_t result_buf_size)。其中 params 结构定义如下:

  struct fsinfo_params {
__u64 resolve_flags;  /* RESOLVE_* flags */
__u32 at_flags; /* AT_* flags */
__u32 flags;    /* Flags controlling fsinfo() specifically */
__u32 request;  /* ID of requested attribute */
__u32 Nth;    /* Instance of it (some may have multiple) */
__u32 Mth;    /* Subinstance of Nth instance */
  };

设计了四种不同的方法来使用 dfd、pathname 和 params->at_flags 指定应该查询哪个文件系统。详情请参见这个 patch 的 changelog (https://lwn.net/ml/linux-kernel/159646180259.1784947.223853053048725752.stgit@warthog.procyon.org.uk/ )。params 结构的其余部分描述了实际请求哪些信息;结果最终会在 result_buffer 中获取到。

params->request 支持很多内容,包括:

  • FSINFO_ATTR_STATFS 返回与 statfs()相同的信息。

  • FSINFO_ATTR_LIMITS 返回文件系统的各种限制,包括最大文件大小、inode 号、用户 ID 号、文件的硬链接、文件名长度等。这些都是以 fsinfo_limits 结构返回的。

  • FSINFO_ATTR_TIMESTAMP_INFO 以一组 binary structure 的形式取得这些文件的时间戳信息;这些信息包括时间戳的最大值和粒度,以内核从来没用过的 mantissa-and-exponent format 来表示。

  • FSINFO_ATTR_MOUNT_POINT 生成一个字符串,显示文件系统的挂载位置。

  • FSINFO_ATTR_MOUNT_CHILDREN 给出了一个结构数组,用来标识 mount 在被查询的文件系统下面的文件系统。完整的可能请求列表比上面的更长。每个请求都以不同的格式返回数据,通常是请求信息的特定二进制结构。对于某些属性,查询可能会返回许多元素,在这种情况下,可以使用 fsinfo_params 结构中的 Nth 和 Mth 字段来确定应该返回哪些。这个 patch(https://lwn.net/ml/linux-kernel/159646187933.1784947.10955424144341330111.stgit@warthog.procyon.org.uk/ )包含了一个示例程序,它使用了一些 fsinfo()的特性,生成了一个显示当前系统的挂载拓扑图的列表。

Complaints and alternatives

fsinfo()的这个提案面临几点阻力。首先是是否真的有这个需要。Linus Torvalds 称它是 "engineering for its own sake, rather than responding to actual user concerns",并想知道为什么 Linux 这么多年都不需要这么个 API,而现在需要了。Torvalds 不太喜欢增加那些最终没人使用的系统调用,所以他通常都会需要人们给出增加新接口的理由。没过多久,就有潜在用户明确表达了他们的需求。Steven Whitehouse 这样说:

The overall aim is to solve some issues relating to scaling to large numbers of mount in systemd and autofs, and also to provide a generically useful interface that other tools may use to monitor mounts in due course too. Currently parsing /proc/mounts is the only option, and that tends to be slow and is certainly not atomic. 

译文:总的目标是解决 systemd 和 autofs 中与挂载了大量文件系统有关的一些问题,同时提供一个通用的有价值的接口,其他工具也可以在适当的时候用来监控挂载情况。目前,解析/proc/mounts 是唯一的选择,但这往往很慢,而且肯定不是原子操作。

util-linux 软件包的维护者 Karel Zak 介绍了拥有数千个挂载点的系统的需求。Lennart Poettering 提供了一长串他想了解的文件系统属性,以及为什么它们会有用。所有这些讨论的最终结果表明人们确实需要某种系统调用来提供文件系统的信息。

不过 fsinfo()的复杂性还是让一些开发者感到担心;对他们来说,它看起来就像是又一个试图做许多种工作的多路系统调用(multiplexer system call)。但也没有人提出一个更好的替代设计方案。有一个简短的题外话,Torvalds 建议了一个 API,在这个 API 中,一个文件的属性可以直接被 open 调用,就好像该文件是一个目录一样。因此,open(当然要用一个特殊的 flag)foo/max_file_size 将可以获取到存放 foo 这个普通文件的文件系统所能支持的最大文件 size。这个想法与 2004 年 reiser4 文件系统对 metadata 的争议性做法(https://lwn.net/Articles/100148/ )非常相似,在讨论中指出这一点似乎也并不是一个政治性的决策。

人们指出,实现这种机制有许多实际困难。甚至精确定义它的语义,看起来也很困难。因此,这个想法被搁置了。估计几年之后肯定有人会再次提出来。

这样一来,这个问题(获取文件系统信息的新 API 应该是什么样子的)就没有结论了。Torvalds 称 fsinfo() 是"confusing and over-engineered",并问道。"我们能不能做一个简单的扩展的 statfs()就完事了,而不是做一个非常复杂的东西,用同一个接口做五件不同的事,结果让它变得非常不合群?" 他进一步建议,fsinfo()使用的一些二进制结构可以用 ASCII 数据代替。他指出,一些文件系统接口已经在使用 ASCII 来处理更复杂的属性,并表示希望一个以 ASCII 导出信息的内核接口能让现在从/proc/mounts 中解析这些信息的代码实现时更轻松。

所以这次讨论的最终结果很可能是试图按照这些思路重新设计 fsinfo()。但这里有一个问题:所需要的信息,就像它所代表的系统一样,本质上是很复杂多样的。等到设计出一个类似于 statfs()的 API,并且可以表达所有这些信息,也可以在未来进行扩展的时候,这个设计有可能会开始看起来很像现在的 fsinfo()。用 ASCII 码代替一些二进制结构似乎不太可能对这种情况有显著帮助。整个工作的最终结果可能是与当前设计非常相似的东西。

全文完
LWN 文章遵循 CC BY-SA 4.0 许可协议。

欢迎分享、转载及基于现有协议再创作~

长按下面二维码关注,关注 LWN 深度文章以及开源社区的各种新近言论~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值