两个入口,同一套页表遍历
按范围进来,还是带着 VMA 进来
walk_page_range(start, end)
按地址范围遍历
每次遍历先 find_vma() 定位起点
walk_page_range_vma(vma, ...)
调用方直接传 VMA
跳过查找
范围由调用方划定
本次改动:四处调用方改用 walk_page_range_vma()
省掉起点查找,但 PFNMAP 差异要逐处交代
现状 · 已知在哪个 VMA,还要再找一次
调用方已知
start 与 end 同属一个 VMA
walk_page_range()
仍从通用入口进来
find_vma()
每次遍历先定位起点
这次查找不会有新结果
范围本来就在一个 VMA 里,调用方的信息没被用上
mincore、mprotect、mlock、migrate_device 都是这种情况
问题 · 四处调用方,四处冗余
它们都能保证范围落在单个 VMA
mincore
do_mincore()
调用方传入的 start 与 end 总在同一 VMA
mprotect
mprotect_fixup()
由 do_mprotect_pkey() 逐 VMA 迭代调用
mlock
mlock_vma_pages_range()
由 apply_vma_lock_flags() 逐 VMA 调用
migrate_device
migrate_vma_collect()
范围由 migrate_vma_setup() 事先验证
四处都不是猜的:单 VMA 由调用约定保证
方案 · 直传 VMA,跳过查找
调用方保证单 VMA,就不必让内核再找
调用方
已知单个 VMA
walk_page_range_vma()
直接传 VMA
页表遍历
不再先 find_vma()
四处调用方不再触发这次 find_vma()
这一步查找从路径上消失
范围还是那一段,VMA 由调用方指出来
查找这一步不再重复
差异 · walk_page_test() 不再被调用
省掉的不只是查找
walk_page_range()
先过 walk_page_test()
VM_PFNMAP 经 pte_hole() 跳过页表遍历
walk_page_range_vma()
不调 walk_page_test()
也就没有 pte_hole() 这一跳
少了这一层,PFNMAP 的 PTE 会被当成普通项处理
四处必须逐处交代
否则这四处的行为会变
逐处 · 四种 PFNMAP 处理
每处的来由不同,处理也不同
mincore
历史上把 PFNMAP 映射报为非驻留
do_mincore() 显式检查 VM_PFNMAP
直接按未映射处理,行为不变
mprotect
prot_none_test() 恒返回 0
钩子直接删掉
mlock
VM_PFNMAP 早被 vma_supports_mlock() 过滤
无须额外处理
migrate_device
VM_PFNMAP 早被 migrate_vma_setup() 过滤
无须额外处理
四条路径的对外行为都不变
预期收益 · 作者未提供性能数据
以下均为代码逻辑推断,不是实测
四处页表遍历各省一次 find_vma()
起点查找不再重复
mprotect 顺带删掉恒为空的 prot_none_test()
少一层空钩子
PFNMAP 逐处核实并妥善处理
行为无变化
空格
播放/暂停
←
→
逐动作
R
重播
⚠
1x