LWN:Rust实现文件系统!

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

Rust for filesystems

By Jake Edge
June 21, 2024
LSFMM+BPF
Gemini-1.5-flash translation
https://lwn.net/Articles/978738/

在 2024 年的 Linux 存储、文件系统、内存管理和 BPF 峰会 (Linux Storage, Filesystem, Memory Management, and BPF Summit) 上,Wedson Almeida Filho 和 Kent Overstreet 联合主持了一个关于使用 Rust 开发 Linux 文件系统的存储和文件系统主题的会议。早在 2023 年 12 月,Almeida 就 发布了一个 RFC 补丁集 (RFC patch set),其中包含一些用于文件系统的 Rust 抽象,这引出了 关于这种方法的一些争议。在会议举行的 5 月中旬,他又 发布了 第二版的 RFC 补丁,他希望与其他与 Rust 相关的主题一起讨论。

目标

在向与会者介绍了他的补丁的状态后,Almeida 列出了一些 Rust-for-Linux 项目 (Rust-for-Linux project) 的目标,这些目标体现在他提出的文件系统抽象中。第一个目标是使用 Rust 的类型系统表达更多需求,以便在编译时捕获更多错误。此外,该项目的开发人员希望自动化一些任务,例如清理资源,这些任务在 C 代码中不容易实现。总的来说,他们的目标是拥有更有效率的文件系统开发体验,减少调试编译器可以发现的问题的时间,以及整体上减少与内存相关的漏洞。

8171cf76e1e99d061cb7e8754c1ecdac.png

Overstreet 说他参加过太多为期两周的 bug 查找活动,一直在寻找方法来避免 bcachefs 中出现此类问题。Rust 语言提供了比他在 C 中所能做的更多东西;它消除了未定义的行为,并提供了一些功能来查看代码内部发生了什么情况。“如果你看不见正在发生的事情,你就无法调试。”他相信由于使用了 Rust,内核开发“在未来几十年内将变得容易得多”。将能够证明用 Rust 编写的代码的正确性,这意味着可能破坏功能开发的 bug 将会大大减少。

Almeida 从他的 幻灯片 中展示了一个 Rust 类型系统如何消除某些类型错误的示例。他指出,当前内核中的 iget_locked() 函数有一组复杂的必备条件。调用者必须检查返回值是否为 null,如果不是,则需要检查返回的 struct inode 的内容来确认它是是一个新的还是已存在的 inode。如果它是新的,则需要在使用之前进行初始化;如果失败,则需要调用 iget_failed(),他说。

关于 iget_locked() 的调用者需要执行的操作的一些细节进行了讨论,Al Viro 对 Almeida 幻灯片中的部分内容表示不赞成。他们进行了来回讨论,Overstreet 观察到,通过将规则封装到 Rust 类型和抽象中,可以避免这种类型的讨论/争论;编译器将知道正确的事情。

Overstreet 指出,Christian Brauner 和 Alice Ryhl 在第一次发布之后帮助改进了这些抽象;特别是,他从 Rust 代码中处理引用计数的方式中学到了很多东西。“这将使我们所有人的生活变得容易得多,”Overstreet 说。

Almeida 展示了一张幻灯片,其中包含了 Rust 中 iget_locked() 的等效代码,名为 get_or_create_inode() 。他说,重要的部分在于返回类型;与 C 语言一样,调用者必须检查是否失败,但成功情况大不相同。如果成功,调用者会收到一个可以使用的常规引用计数 inode(当 inode 对象不再被引用时,其引用计数会自动递减),或者它会收到一个新的 inode,如果该 inode 从未被初始化,它会自动调用相当于 iget_failed() 的函数。如果它曾经被初始化(只能被初始化一次),它就会变成一个具有自动引用计数递减的常规 inode。所有这些都是通过类型系统强制保证的。

Viro 对此在实践中如何运作表示怀疑。他想知道这些约束是在源代码的什么地方定义的。Almeida 说,核心想法是从 Viro 以及其他的文件系统开发人员那里确定约束是什么,然后创建可以强制执行这些约束的类型和抽象。

脱节(Disconnect)

Dave Chinner 提出了 C API 和 Rust API 中名称之间的脱节问题,这意味着开发人员无法查看 C 代码并知道等效的 Rust 调用是什么。他说,应该使用相同的名称,否则对于现有的开发社区来说将完全陌生。此外,当 C 代码发生变化时,Rust 代码需要随之变化,但谁来做这项工作呢?Almeida 同意这是一个需要讨论的问题。

就重命名的函数而言,他不反对将名称改为与 C API 相匹配,但他认为 iget_locked() 不是一个特别好的名称。也许可以利用这个机会创建更好的名称。

他们对这个例子进行了一些进一步的讨论,Viro 说这不是一个好的选择,因为 iget_locked() 是一个库函数,而不是 superblock 对象的成员函数。Almeida 说 get_or_create_inode() 可以变成一个库函数;他的例子只是为了展示如何将约束编码到类型之中。

Brauner 说,需要决定 Rust 抽象是否将是通用的,旨在用于所有内核文件系统,或者是否只关注用 Rust 编写更简单的文件系统所需的函数。在处理 get_or_create_inode() 等函数比 iget_locked() 编码了更多约束的情况时,还存在一个长期问题。随着 C 代码的演变(至少在最初,这方面的变动将比 Rust 代码更快),需要保持两个 API 同步。

Overstreet 说,这归结为一个问题,即重构和清理是否将作为添加 Rust 抽象的一部分进行;他坚信这是必需的。但 James Bottomley 说,不仅仅是这些。对象生命周期正在被编码到 Rust API 中,但在 C 中没有等效的代码;如果有人在一边改变了对象的生命周期,另一边就会出现 bug。

Chinner 说,也存在一些问题,因为 inode 对象的生命周期有时是跟具体文件系统相关的。将单一生命周期理解编码到 API 中意味着其函数将不适用于某些文件系统。Overstreet 说,不使用 VFS API 的文件系统将无法从中受益,但 Chinner 说,VFS inode 只是一个结构,由文件系统管理其生命周期。Almeida 说,这个例子只会被当前调用 iget_locked() 并可以从中受益的文件系统使用。Rust 开发人员并不试图强迫文件系统改变它们的工作方式。

分配痛苦

Ted Ts'o 说,问题的一部分是有人试图让“每个人都转而信奉”Rust 宗教;他说,这不会发生,因为 Linux 中有 50 多个不同的文件系统不会立即被转换。C 代码将继续改进,如果这破坏了 Rust 绑定,就会破坏依赖它们的那些文件系统。在可预见的未来,Rust 绑定将是二等公民,他说;损坏的 Rust 绑定是 Rust-for-Linux 开发人员的问题,而不是整个文件系统社区的问题。

他建议继续开发 Rust 绑定,同时继续发展 C 代码。随着这些变化的发生,“我们将找出将大量语义编码到类型系统中这个概念是好是坏”。他认为,一两年后,这个问题的答案会变得很清楚;但实际上,这将归结为一个“痛苦分配问题(where does the pain get allocated)”。在他看来,像这样的重大改变几乎总是归结为一个“痛苦分配问题(pain-allocation question)”。

Almeida 说,他并不是试图使 C API 固定下来不可以演进了;他的目标是让文件系统开发人员解释 API 的语义,以便他们可以将这些语义编码到 Rust 中。Bottomley 说,随着更多这些语义被编码到绑定中,它们在同步方面会变得更加脆弱。一些人表示不同意,以各种“不”或类似的回复来表达。Almeida 说,任何 API 的用户都是一样的;如果 API 发生改变,用户需要更新。但 Ts'o 语重心长地说,不是每个人都会学习 Rust;如果他进行了一些更改,他会修复所有受影响的 C 代码,但是,“因为我不懂 Rust,我不会修复 Rust 绑定,抱歉”。

Viro 回到他对提议的 iget_locked() 替代品的异议。他认为的根本问题是依赖方法(methods)而不是函数(functions);使用方法不是正确的前进方向,因为参数没有明确指定。但 Overstreet 说,对方法的抱怨来自像 C++ 这样的语言,这些语言过于依赖继承,这“是一个糟糕的想法”。Rust 没有这样做;Rust 中的方法基本上只是一个语法元素。

他们对究竟是什么被编码到类型中进行了一些讨论。Jan Kara 说,inode 有一些与之相关的行为,比如它的引用计数及其处理方式,但还有其他行为是 iget_locked() 函数固有的。Overstreet 和 Almeida 说,这两个部分都编码到类型中,但分开编码;使用 inode 类型的其他函数可能具有具有不同属性的返回值。

Viro 阐述了他对 inode 在 VFS 中的工作方式的一些理由。他同意从小处开始,看看事情会走向何方。Overstreet 建议,也许使用的例子不是一个好的起点,“因为这是复杂的情况”。“哦,不,不是的,”Viro 笑着回答,会议结束。

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

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

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

d61261e4bfde35d5e5013d4179fa4a99.jpeg

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值