LWN:改进page-fault的可扩展性!

文章讨论了Linux内核中page-fault处理的可扩展性问题,特别是mmap_lock锁和监控任务与工作负载间的优先级倒置。开发者正致力于通过RCU、mapletree和更细粒度的锁定来解决这些问题,同时提出了一些未来可能的优化方向,包括speculativepage-faulthandling和减少对mmap_lock的依赖,目标是实现lock-freefaulthandling以提高性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

Improving page-fault scalability

By Jonathan Corbet
May 29, 2023
LSFMM+BPF
DeepL assisted translation
https://lwn.net/Articles/932298/

某些话题总是每年都要回到开发会议上来讨论一次,通常是因为开发人员仍在努力针对某个特定的问题寻找一个可行的解决方案。其中一个就是内核的 page-fault 处理代码缺乏可扩展性(scalability)的问题,所以看到这个问题出现在 2023 年 Linux 存储、文件系统、内存管理和 BPF 峰会的议程上,我们毫不意外。Matthew Wilcox 在内存管理主题上主持了一个会议来讨论 page-fault 处理的现状以及如何进一步改进。

他首先指出,Suren Baghdasaryan 在过去一年中一直在这方面做了大部分工作。谈到 page-fault 的可扩展性,有两个主要的问题:每个进程都有的 mmap_lock 锁的竞争,以及监控任务(monitoring task)和实际工作负载之间的优先级倒置问题(例如当监控任务从/proc/pid/smaps 读取数据时就会出现这种情况)。他说,在 2022 年讨论过一些解决这些问题的方案,包括后来的一个长期工作来实现投机性页面故障处理(speculative page-fault handling)、在大部分处理路径中使用 read-copy-update(RCU)、在虚拟内存区(VMA)级别上加锁、以及使用最近新增的 maple tree 数据结构来实现更细粒度的加锁动作。

1ae14007cf3b3edd2cba5c5762f97f03.png

在那之后,已经用 maple tree 取代了红黑树来管理进程的地址空间。Baghdasaryan 已经实现了 RCU lookup 和 per-VMA 加锁,并将其推上了 upstream。仍在进行的工作还有一组处理在 page cache 中具有最新内容 page 的基于文件内容的 VMA 的 fault(可以在不发起 I/O 操作的情况下处理)。还有一项工作正在进行中,用来改善对 swap cache 中的 page fault 处理。这两种情况现在都必须回退到 mmap_lock。

换句话说,我们将继续努力让更多的地方可以在不使用 mmap_lock 的情况下进行处理。未来的项目中将增加更多的情况,包括发起(initiating)和 等待(waiting) I/O、为/proc/pid/smaps 提供数据、通过 userfaultfd() 处理的 fault、由设备驱动导致的 VMA 中的 fault,等等。总有一天,将不再有任何情况需要转换,届时 mmap_lock 可以被彻底移除。

在解释 "waiting for I/O " 这种情况时,Wilcox 说,他正在研究 swap-backed 和 file-backed 类型的 page。目前的计划是对正在读取的文件的增加引用计数,去掉 lock,然后睡眠。一旦 I/O 完成,fault 处理过程会从头开始,从而能确保其他地址空间可能已经发生的变化也得到体现。他问大家这是否是正确的实现方式,或者还是在 I/O 进行时来直接阻止对发生 fault 的 VMA 的改动更好。

Michal Hocko 回答说,这两种情况是很不一样的,也许应该以不同的方式处理。在 swap 场景下,在等 fault page 被读入的同时,拥有这个 page 的进程有可能就取消了内存映射。可以通过在等待时持有 VMA 锁来避免这种情况下的问题。他说,这种方法在 file-backed 场景并不可行,因为 VMA 没有映射到进程可见的对象上。

Wilcox 说,还有一个潜在的问题是,在一个进程中,有可能会出现两个线程同时调用 malloc()的情况。这两者中的任何一个最终都可能会调用 mmap()来获得更多的内存从而满足分配请求。这两个调用通常会创建两个 VMA,但内核可能会很聪明地把这两个调用合并起来;这反过来又会在 VMA 锁上产生应用程序没有预料到的竞争的情况。Steve Rostedt 建议使用 tracing 来获取一些真实数据,证明这是否是一个现实世界存在的真实问题,但 Hocko 说,他经常看到一些牵涉到 "一个名称未知的数据库产品" 的 bug report,可以看到出现了这种竞争情况。

Wilcox 说,在不持有 mmap_lock 的情况下启动 I/O 的情况比较容易处理。已经确定的是,在内存管理锁(如 per-VMA 锁)被持有的情况下调用驱动程序是一件安全的事情,即使没有抓 mmap_lock。

他继续说,监控程序的场景,还有一些特有的挑战。可以在只持有 RCU lock 的情况下遍历 VMA 列表,有一些/proc 接口可以在这种模式下工作;"这只是一个代码实现的问题"。但 smaps 文件更复杂;为了收集它所需的信息,它必须能够保持 page table 不被释放,而这就需要抓住 mmap_lock。在 x86 架构上,还需要禁用中断,这是一个 "愚蠢的历史遗产,我们应该直接去掉",他说。Vlastimil Babka 说,这种行为是由于需要阻止处理器间的中断,这些中断会导致 TLB buffer 被 flush 掉。

Jason Gunthorpe 说,page-table 释放动作也许可以用 RCU 保护,但这需要在 page 结构中增加一个 rcu_head 结构;Wilcox 回答说这已经存在了,但在 page-table 释放时还没有使用它。Mike Rapoport 说用 RCU 来保护页表释放是可行的,Wilcox 回答说他希望看到这样做,但那里 "可能会有陷阱"。不过 Hocko 说,这可能是一个很好的低风险项目,可以让人研究一下。

对于 userfaultfd()的情况,也就是把 fault 报告给用户空间来让其解决,Wilcox 承认说他缺乏想法。Baghdasaryan 说,这看起来跟 swap 的情况类似,在通知用户空间之前丢掉锁也是可行的方案。

对于 device-driver VMA 来说还有一个问题,就是驱动本身可能要求得持有 mmap_lock,所以直接丢弃它的话很可能会导致不愉快的 bug。Wilcox 建议说,他确实缺乏对内核中的每一个驱动程序针对这类问题都进行审计的动力。取而代之的是,驱动程序将需要明确指出他们准备在不保留锁的情况下来处理 fault。驱动程序还必须在有需要的时候明确声明在故障处理程序中不放弃 mmap_lock。驱动程序可以实现 map_pages() VMA 操作来提前映射他们的 page,这是将 page 映射到用户空间的最有效方式。 map_pages()受到 RCU read lock 的保护,这意味着驱动程序在使用它时无法 sleep。

Gunthorpe 说,驱动程序必须准备好出现进程 fork 导致创建出两个独立的 VMA 并且都是由 driver-provided 的情况。由于每个 mapping 都将受到单独的 mmap_lock 的保护,所以驱动程序在任何情况下都不能依赖这个锁。Michel Lespinasse 说,尽管如此,还是有依赖 mmap_lock 的驱动程序,所以需要某种机制能允许这种方式,以便能够在不持有 lock 的情况下该驱动程序。不过现在 per-VMA lock 只针对 anonymous VMA,所以缺少 mmap_lock 对驱动程序来说不是问题。

最后,Wilcox 谈到了完全删除 mmap_lock 的想法,这是他希望有一天能达到的目标。不过,这还是会是一个持续多年的项目,就像在 2011 年最终完成移除 big kernel lock 大内核锁一样。朝着这个方向的一个重要步骤就是停止使用 lock 来保护 VMA tree,而是把每个使用场景都改成自己的 lock。Lespinasse 说,他看不出如何能做到这一点;特别是与 reverse mapping 交互的情况会使事情变得复杂。

会议结束时,有人指出,追求可扩展性的工作并不会随着 mmap_lock 的移除而结束;Wilcox 已经在期待着在不占用 VMA 锁的情况下处理 fault。我们有理由相信 VMA 锁会导致 cache line 竞争,尽管需要用 perf 进行一些分析来验证这个观点。他说,其实是有可能走向 lock-free fault handling (不加锁进行 fault 处理),但这会是相当复杂的工作,他只有在看到明确性能需求时才会继续去追求这个方向。

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

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

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

format,png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值