mm: remove wait_on_page_writeback()
内存管理 · page→folio 兼容层收尾 · ceph 写回路径 folio 化
💡 一句话总结
内核在把基于 struct page 的页面 API 全面迁移到 struct folio,而 wait_on_page_writeback() 是 folio_wait_writeback() 的一个兼容包装,只剩 ceph 写回同步路径这一个调用者;本系列先把该调用者迁移到 folio API,随后删除这个失去调用者的兼容包装函数及其声明——纯重构、作者明确"无功能变化",是 folio 化大工程的收尾步骤。
📋 补丁基本信息
| 项目 | 内容 |
|---|---|
| 补丁类型 | 重构 / 死代码清理(删除兼容包装,语义不变) |
| 状态 | In Review(v1,首版,尚无 Ack/Review) |
| 当前版本 | v1 · PATCH 3/4 |
| 系列主题 | mm, ceph: remove wait_on_page_writeback()(4 个补丁) |
| 作者 | Tal Zussman <tz2294@columbia.edu>(Columbia University) |
| 提交日期 | 2026-08-02 16:50 UTC |
| 改动范围 | 本补丁 2 文件(include/linux/pagemap.h + mm/folio-compat.c),+0/−7 |
| 基准分支 | mm-new(作者在 cover letter 中说明) |
📊 速览卡片
核心机制
删兼容包装
优化目标
folio 化收尾
适用场景
ceph 写回等待
实测提升
未提供(重构)
🎯 解决什么问题
背景 / 原始动机
内核自 2022 年起由 Matthew Wilcox 主导,把以
struct page(单页)为中心的 mm API 迁移到 struct folio(一页或多页的复合单位)。迁移期间的"旧 API"被收在 mm/folio-compat.c,以兼容包装的形式继续存在,供尚未迁移的调用者使用。**每清空一个兼容包装的全部调用者,就可以删除这个包装**——这是 folio 化工程"增量迁移、逐批拆除"的标准节奏。wait_on_page_writeback() 正是这样一个待拆除的兼容包装。
系统层面:wait_on_page_writeback 是什么
wait_on_page_writeback(page) 的作用是:若该页的 PG_writeback 写回标记仍被置位,则睡眠等待写回完成(用于"写回未结束不能复用/释放页面"的场景)。folio 化后的等价实现是 folio_wait_writeback(folio)。兼容包装的实现只是 folio_wait_writeback(page_folio(page))——把 page 还原成 folio 再调用 folio 版本,**与直接调用 folio 版完全等价**。删除它并不改变任何运行行为,而是清掉一层多余的 page→folio 往返与一个已无调用者的导出符号。
场景层面:ceph 写回同步路径的"缺陷"
ceph 的快照写回路径
ceph_wait_until_current_writes_complete() 需要等待当前快照上下文(snapc)下所有脏页的写回完成。它用 filemap_get_folios_tag(PAGECACHE_TAG_WRITEBACK) 拿到一批 folio,却要把每个 folio 转回 &folio->page,再走 page 版 wait_on_page_writeback()(内部又转回 folio)——**两次无谓的 folio↔page 转换**。这正是 folio_batch 迭代器与旧 page API 之间的"摩擦点":迭代器天然产 folio,旧 API 却要求 page。
🧩 核心机制
整个系列 4 个补丁分工协作,本补丁(3/4)是"最后一步的 mm 侧收尾":
系列拆解(4 个补丁)
| 补丁 | 文件 | 作用 |
|---|---|---|
1/4 ceph: add ceph_folio_snap_context() | fs/ceph/addr.c | 新增 folio 版快照上下文助手(读 folio->private),供后续替换 page 版 |
2/4 ceph: convert ceph_wait_until_current_writes_complete() to folios | fs/ceph/addr.c | 把最后一个 wait_on_page_writeback() 调用者改成 folio_wait_writeback() |
| 3/4 mm: remove wait_on_page_writeback()(本补丁) | pagemap.h + folio-compat.c | 调用者清零后,删除兼容包装函数及其声明 |
4/4 ceph: remove page_snap_context() | fs/ceph/addr.c | 删除已被 folio 版取代的 page 版助手,并更新注释 |
本补丁改了哪两个地方、为什么
①
②
include/linux/pagemap.h:删掉 void wait_on_page_writeback(struct page *page); 的声明。因为函数已删除,声明必须同步移除,否则留一个"声明了但不存在"的符号(LTO/编译期会因未定义而失败)。②
mm/folio-compat.c:删掉函数体与 EXPORT_SYMBOL_GPL(wait_on_page_writeback)。这个文件就是"过渡期 page 兼容层"的存放处,包装每失去全部调用者就整段删除,是 folio 化工程的例行维护。保留 end_page_writeback、mark_page_accessed 等仍有调用者的兼容函数不动。
🔬 关键代码
本补丁(3/4)的完整 diff(逐字取自 lore):
diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
index 4e8b2b29f6d3..c8666fd14d3d 100644
--- a/include/linux/pagemap.h
+++ b/include/linux/pagemap.h
@@ -1335,7 +1335,6 @@ static inline int folio_wait_locked_killable(struct folio *folio)
}
void folio_end_read(struct folio *folio, bool success);
-void wait_on_page_writeback(struct page *page);
void folio_wait_writeback(struct folio *folio);
int folio_wait_writeback_killable(struct folio *folio);
void end_page_writeback(struct page *page);
diff --git a/mm/folio-compat.c b/mm/folio-compat.c
index a02179a0bded..ae0271591d37 100644
--- a/mm/folio-compat.c
+++ b/mm/folio-compat.c
@@ -23,12 +23,6 @@ void end_page_writeback(struct page *page)
}
EXPORT_SYMBOL(end_page_writeback);
-void wait_on_page_writeback(struct page *page)
-{
- return folio_wait_writeback(page_folio(page));
-}
-EXPORT_SYMBOL_GPL(wait_on_page_writeback);
-
void mark_page_accessed(struct page *page)
{
folio_mark_accessed(page_folio(page));▲ 两段删除一一对应:头文件删声明,实现文件删函数体 + GPL 导出。周围保留的 folio_wait_writeback / end_page_writeback 等符号是该文件内仍有调用者的兼容函数。
真正"动逻辑"的是配套补丁 2/4(ceph 侧最后一位调用者的迁移,关键行):
@@ -1640,10 +1640,10 @@ void ceph_wait_until_current_writes_complete(...)
for (i = 0; i < nr; i++) {
- page = &ceph_wbc->fbatch.folios[i]->page;
- if (page_snap_context(page) != ceph_wbc->snapc)
+ folio = ceph_wbc->fbatch.folios[i];
+ if (ceph_folio_snap_context(folio) != ceph_wbc->snapc)
continue;
- wait_on_page_writeback(page);
+ folio_wait_writeback(folio);
}▲ 循环直接从 folio_batch 取 folio,去掉 &folio->page 转换与 page 版包装的二次还原;ceph_folio_snap_context() 直读 folio->private(PATCH 1/4 引入)。行为等价(解读(AI 分析):folio_batch 里的 folio 是 head,page_folio(&folio->page) == folio 恒成立)。
📈 性能影响
基准数据
未提供。作者在 cover letter 中明确声明"No functional change intended"(无功能变化)。本补丁删除的是一个已经没有任何调用者的兼容包装,不存在运行时路径,因此也没有性能测试。
定性影响(解读(AI 分析))
folio↔page 两次转换和一次 page_folio() 还原。该路径只在 sync_mode == WB_SYNC_ALL(同步写回)且存在 WRITEBACK 页时执行,属于低频路径,量级上收益可忽略(解读(AI 分析))。EXPORT_SYMBOL_GPL 符号与整段兼容代码,降低 mm 层维护与 API 表面积。🔄 方案演进
版本演进
本系列为 v1 首版(系列时间线仅一条记录,subject 无版本号前缀)。截至 lore 索引截止时间(2026-08-03 19:19 UTC),未见 v2 或维护者 Ack/Review trailer。
设计上下文:为什么现在才删
wait_on_page_writeback() 并非一直只剩 ceph 一个调用者。它曾是 reiserfs、f2fs、ext4、vmscan 等多个路径的常客,随着各子系统逐个 folio 化(如 f2fs 2018 年修复写回等待顺序、ext4 2011 年清理等待调用),调用者逐步清零。到本系列为止只剩 ceph 一处,于是"转换最后调用者 + 删除包装"两件事可以合入同一系列(作者在 cover letter 说明)。
💬 讨论焦点
维护者回复 / Ack / Review
截至报告时点,未检索到公开回复,系列中亦无 Acked-by / Reviewed-by trailer(基于 lore 系列时间线,截止 2026-08-03 19:19 UTC)。收件人覆盖 ceph 与 mm 维护者(Ilya Dryomov、Matthew Wilcox、Jan Kara、David Hildenbrand、Lorenzo Stoakes、Zi Yan 等)。该系列发布于 2026-08-02,仍处于早期 review 窗口。
cover letter 主动披露的交叉冲突
作者在 cover letter 中明确指出本系列基于 mm-new,且与 Zi Yan 的系列 "Remove PG_private by using page/folio->private checks instead" 可能存在轻微冲突;Zi Yan 系列落地后应可进一步简化
ceph_folio_snap_context()(不再需要 folio_test_private() 检查)。这是当前最值得跟踪的 review 关注点(解读(AI 分析))。
⚠️ 风险与局限
潜在回归 / 边界
合入顺序依赖:本补丁(3/4)删除包装的前提是 2/4 已把所有调用者清空。若单独合入 3/4 而未合 2/4,内核会因
导出符号移除:删除
冲突面:基于 mm-new,与 Zi Yan PG_private 系列可能冲突,需要 rebase 协调(作者已预期)。
fs/ceph/addr.c 仍调用 wait_on_page_writeback() 而编译失败——必须按系列顺序合入(解读(AI 分析))。导出符号移除:删除
EXPORT_SYMBOL_GPL(wait_on_page_writeback) 会破坏依赖它的外部 GPL 模块(如有)。这是内核删除导出符号的标准操作,需走常规的过渡惯例。冲突面:基于 mm-new,与 Zi Yan PG_private 系列可能冲突,需要 rebase 协调(作者已预期)。
严重度:LOW · 纯死代码清理,无运行行为变化;唯一实质风险是合入顺序与跨系列 rebase
🔗 交叉引用
相关代码 / 补丁
mm/folio-compat.c:26-29(定义 + EXPORT_SYMBOL_GPL)、include/linux/pagemap.h:1243(声明)、fs/ceph/addr.c:1639(最后一个调用者,已由 2/4 迁移)——均经内核工作树核实。folio->private 语义相关。mm/folio-compat.c 整体是 page 兼容层的存放处,本补丁是其中又一个被清空的条目。✅ 关键洞察
- 性质:本补丁是"最后一个调用者迁移完成后,删除对应兼容包装"的标准 mm 例行清理——纯死代码删除,无行为变化(作者明示)。
- 真正的价值在 ceph 侧:系列的实际工作(1/2/4)是 ceph 写回路径 folio 化,本补丁(3/4)是其"后置清理条件"。
- 信号意义:每个 page 兼容包装的消失,都是内核 folio 化推进的里程碑;本补丁说明 ceph 这一重量级文件系统写回路径的 folio 迁移已基本完成。
- 数据:无性能基准(重构);关注点应在 Zi Yan 系列的冲突协调与合入顺序。
⚠️ 免责声明
本站内容均由 AI 基于公开知识辅助生成,仅供学习参考,请勿直接引用作为依据。作者不对信息的准确性、完整性及适用性作保证,亦不对因使用本站内容产生的任何损失承担责任。