背景

balance_dirty_pages 在 writer 自由写入时会做一道 proactive 检查:当全局脏页数超过全局 background threshold(bg_thresh)时,提前启动 background writeback,趁 writer 还没被限流就把脏页往磁盘排。这道提前排水让 writer 少撞"throttle wall"。

┌────────────────────────────────────┐
│ strictlimit 设备的每域脏页先涨起来 │
└─────────────────┬──────────────────┘
                  ▼
┌────────────────────────────────────┐
│  后台回写只看全局阈值,此刻还没到  │  该域已超自己的背景阈值,却无人提前排水
└─────────────────┬──────────────────┘
                  ▼
┌────────────────────────────────────┐
│       写者一路写,直撞限流墙       │
└────────────────────────────────────┘

但它只看全局阈值。对 strictlimit BDI(如 fuse,有独立的 per-writeback-domain 限流配额),per-wb 的脏页数可以率先超过它自己的 per-wb bg_thresh,而此刻全局阈值还没到。于是这道 proactive 检查对这种情况从不触发,writer 一路自由写下去,直到脏页堆到限流线,直接撞墙。

问题

  • proactive background writeback 只看全局脏阈值
  • strictlimit BDI 的 per-wb 脏页可先超 per-wb bg_thresh
  • 此刻全局未达阈值,background writeback 不提前触发
  • writer 一路写到撞 throttle wall

方案

给 strictlimit BDI 补一道 per-wb 阈值检查:当 wb_dirty 超过 wb_bg_thresh 时就启动 background writeback,在 writer 撞墙之前把脏页排掉。

旧:只看全局阈值
┌──────────────────────────────┐
│ 每域脏页超自己背景阈值不触发 │
└──────────────┬───────────────┘
               ▼
┌──────────────────────────────┐
│  全局未达阈值,无人提前排水  │
└──────────────────────────────┘

新:strictlimit 设备补每域阈值
┌──────────────────────────────┐
│ 每域脏页超自己背景阈值即触发 │
└──────────────┬───────────────┘
               ▼
┌──────────────────────────────┐
│ 后台回写提前排水,写者不撞墙 │  匹配全局检查给普通设备的提前行为
└──────────────────────────────┘

这样 strictlimit BDI 也获得了与全局检查给非 strictlimit BDI 提供的同样的 proactive 排水行为:脏页一到该域的背景线就提前动手,而不是干等全局阈值、最终撞墙。

收益

作者在 fuse 上用 fio 测 buffered writes(--ioengine=psync --rw=write --bs=128k --size=2G --numjobs=4 --ramp_time=10 --runtime=20 --time_based --group_reporting=1 --direct=0):

指标 变化
fio buffered writes(fuse) 约 +3%~4%

per-wb 阈值检查让 background writeback 提前排水,writer 少撞 throttle wall,fuse 上 buffered writes 提升约 3-4%。