buffered write
page cache 变脏
dirty page
wb 与 NR_FILE_DIRTY 都记账
balance_dirty_pages()
由 ..._ratelimited_flags() 调用
脏页平衡 / 限流
for (;;) 限流循环
io_schedule_timeout(pause)
睡够 pause,醒来再查阈值
兜底规则
writer 还在被节流
→ writeback 必须在跑
否则就是干等
被误删的兜底(本次恢复)
if (unlikely(!writeback_in_progress(wb)))
wb_start_background_writeback(wb);
64dd89ae01f2
mm/block/fs: remove laptop_mode
移除旋转盘时代的省电特性
laptop_mode 原本做什么
延迟、合并回写,减少磁盘转动
laptop_mode_timer_fn / laptop_io_completion
目标:省电,不是脏页节流
同一补丁里被连带删除
if (unlikely(!writeback_in_progress(wb)))
wb_start_background_writeback(wb);
与 laptop_mode 无关的兜底
→ 无条件启动回写
误伤
laptop_mode ≠ 无条件启动
两件事被当成一件删掉
限流路径从此少了兜底
移除笔记本模式只是顺带误删,该逻辑与笔记本模式无关
全局域 gdtc
nr_dirty
gdtc->bg_thresh
全局 bg_thresh 未超
strictlimit BDI
per-wb 阈值
wb_dirty vs wb_bg_thresh
局部可能先超
memcg 域 mdtc
自己的 dirty 计数
自己的阈值
也可能先超
strictlimit:per-wb 已超,全局仍未超
per-wb 阈值
已超
全局 bg_thresh
未超
memcg:自己的阈值已超,全局仍未超
memcg 阈值
已超
全局 bg_thresh
未超
全局检查不成立
nr_dirty > gdtc->bg_thresh → false
→ 不会主动启动 background writeback
检查阈值
freerun? 超限?
算 pause
task_ratelimit
io_schedule_timeout(pause)
TASK_KILLABLE 睡眠
醒来再查
writer 已睡,脏页还在
dirty 计数不降
writeback 进行中?
没有
每轮醒来都一样
dirty 还在,回写仍没开始
→ 严重停顿
fuse · buffered write
1,400 MiB/s → 2,000 KiB/s
约 700 倍回归
balance_dirty_pages() 循环内
balance_domain_limits(gdtc, strictlimit);
if (!writeback_in_progress(wb) &&
nr_dirty > gdtc->bg_thresh)
wb_start_background_writeback(wb);
...
← 兜底插在这里
mem_cgroup_flush_foreign(wb);
之后才进入限流计算与 pause
恢复:无条件启动
if (unlikely(!writeback_in_progress(wb)))
wb_start_background_writeback(wb);
不看 nr_dirty,不看哪个域超限
只要还没回写,就启动一次
主动路径
全局超 bg_thresh
提前排掉脏页
兜底路径
进入限流就启动
局部超限也不空等
只要 writer 还在被节流,就一定有 writeback 在跑
无论 IO 因为什么原因被限流
修复前(误删后)
2,000
KiB/s
fuse · buffered write
恢复兜底
修复后(恢复后)
1,400
MiB/s
回到误删前的水平
同一负载的两个单位:1 MiB/s = 1,024 KiB/s
≈ 700×
吞吐回归幅度
1,400 MiB/s ÷ 2,000 KiB/s ≈ 700
恢复一段兜底,消除约 700 倍的性能回归
因果链
兜底被误删
局部阈值先超
限流却无回写
严重停顿
恢复无条件启动
为什么必须无条件
节流等待的是「脏页被写回」
全局阈值没超 ≠ 没有限流
per-wb / memcg 可能先超
没有回写 → 等不到 → 干等
恢复后的保证
if (!writeback_in_progress(wb))
wb_start_background_writeback(wb);
每轮限流循环都检查一次
与 laptop_mode 无关,是独立兜底
兜底逻辑:让「被节流」与「有回写在跑」始终同时成立
空格
播放/暂停
←
→
逐动作
R
重播
⚠
1x