v3
2026-10-21
热插拔分配器竞态修复 · v3
修复内存热插拔重建zonelist时分配器竞态,增加preferred zone快照及分配、hugetlb、alloc_contig重试。
原始补丁链接
子 Patch(8)
1/8
mm/page_alloc: detect zonelist rebuilds from memory hot-add
把 zonelist_update_seq 重试检查从 CONFIG_MEMORY_HOTREMOVE 扩到 CONFIG_MEMORY_HOTPLUG,覆盖热添加首个区块触发的原地重建,避免 __GFP_THISNODE 看到中间态而误失败。
2/8
mm/page_alloc: snapshot the preferred zone against shrink rebuilds
在 get_page_from_freelist()/alloc_pages_bulk_noprof() 中只读取一次 ac->preferred_zoneref->zone 并快照使用,避免 zone offline 重建 zonelist 时槽位变 NULL 导致 zone_statistics() 空指针。
3/8
mm/mmzone: read each zoneref slot once when filtering by nodemask
修改 __next_zones_zonelist() 只读取一次 zoneref 槽并缓存 zone,再据此做 nodemask 过滤,防止并发重建把第二次读取变成 NULL 引发 zone_to_nid() 崩溃。
4/8
mm/page_alloc: pass the zone, not the zoneref, to reclaim_retry_zone
让 should_reclaim_retry() 把已解析的 zone 传给 reclaim_retry_zone tracepoint,而非 zoneref 槽,避免并行重建后 tracepoint 二次读取到 NULL 并解引用。
5/8
mm/page_alloc: retry allocations that raced with a zonelist rebuild
在分配成功路径也检查 zonelist_update_seq,若与重建竞争则释放刚分配的页并重试,避免 GFP_KERNEL 落入 ZONE_MOVABLE 或 nodemask 请求越过节点掩码。
6/8
mm/hugetlb: retry the pool walk when the zonelist is rebuilt
在 dequeue_hugetlb_folio_nodemask() 的 zonelist 遍历中,每次使用返回 zone 前检查 zonelist_update_seq,变化则重启并重置上次节点,防止从错误节点取 hugetlb 池页。
7/8
mm/page_alloc: retry alloc_contig_pages() when the zonelist is rebuilt
Onlining the first block of a zone rebuilds every zonelist in place, shifting the slots after the new zone. alloc_contig_pages() can then take a range from a zone or node its filters rejected. Writin
8/8
mm/page_alloc: keep a zone's pagesets when it goes empty
When offlining empties a zone, zone_pcp_reset() frees its pagesets while the vmstat worker can still hold one across cond_resched(): CPU 0 CPU 1 refresh_cpu_vm_stats()