vrealloc
vmalloc 的 realloc
可原地调整大小
缩小时不换地址
缩小
size <= old_size
返回原指针
只更新 requested_size
KASAN shadow 同步
物理页
vm->pages[] 仍在
映射仍在
直到 vfree
地址范围保留
场景
分配缩小后继续用
尾部页不再需要
旧行为 · 只改记账
shrink 路径
memset 可选
return p
记账
requested_size = size
kasan_vrealloc()
vm->nr_pages 不变
vm->size 不变
物理页
尾部页仍映射
仍占 page allocator
仍计入 NR_VMALLOC
等待 vfree
问题
不再使用的页
没有归还
浪费 · 到 vfree
缩小后继续运行
尾部页不能用
却一直占内存
持续时间
直到整段 vfree
可能很长
按分配生命周期
不是瞬时浪费
TODO
vrealloc 早期 TODO
unmap 尾部页
归还 page allocator
本系列兑现
浪费
物理内存紧贴不了
物理占用虚高
方案 · 跨页释放
new_nr_pages = PAGE_ALIGN(size) >> PAGE_SHIFT
new < old 才释放
至少一整个页
旧
只改 requested_size
页全留着
到 vfree
物理占用不降
新
unmap 尾部
free 尾部
保留虚拟地址
只 release 物理页
启发式
跨页边界
至少一个完整页
机制 · 释放与配套
vm_area_free_pages()
kmemleak_free_part()
nr_pages 更新
页释放
vunmap_range()
free_pages_bulk()
pages[] = NULL
NR_VMALLOC 记账
同步
节点 busy.lock
更新 nr_pages
通知 kmemleak
避免 scanner fault
顺序
先更新 nr_pages
再 unmap / free
铺路 · 页数账目
grow-in-place 检查
vread_iter
都改用 nr_pages
grow-in-place
size <= nr_pages << PAGE_SHIFT
不再用 area size
避免写回已释放页
否则 full realloc
vread_iter
VM_ALLOC 用 nr_pages
其它 mapping 用 area size
读范围不越界
shrink 后仍正确
前置 patch
helper + 页数账目
为 shrink 铺路
边界 · 哪些分配跳过
不是所有 vmalloc 都能 shrink
大页 / 权限 / 用户映射
还有 NOFS / NOIO
跳过
page_order > 0
VM_FLUSH_RESET_PERMS
VM_USERMAP
GFP_NOFS / GFP_NOIO
原因
大页要 split
权限归 vfree
用户映射按原 size
kmemleak 可能递归
其余
仍走 shrink
页数未下降就保留页
收益与测试 · 无 benchmark
没有性能数据
只讲机制预期
test_vmalloc 覆盖
机制预期
缩小即归还
物理占用更紧贴
不再占到尾页 vfree
生命周期越长越明显
测试
grow-realloc
shrink 跨页
shrink 同页
grow-in-place
边界
测试验证 4 条路径
不承诺吞吐提升
空格
播放/暂停
←
→
逐动作
R
重播
⚠
1x