YAOTU INSIGHTS

page_alloc __offline_isolated_pages

page_alloc __offline_isolated_pages
__offline_isolated_pages是内存热移除流程中的核心函数用于在页面已被成功隔离的前提下将它们从伙伴系统中彻底移除并标记对应的内存段为离线状态。核心实现unsigned long __offline_isolated_pages(unsigned long start_pfn, unsigned long end_pfn) { unsigned long already_offline 0, flags; unsigned long pfn start_pfn; struct page *page; struct zone *zone; unsigned int order; offline_mem_sections(pfn, end_pfn); zone page_zone(pfn_to_page(pfn)); spin_lock_irqsave(zone-lock, flags); while (pfn end_pfn) { page pfn_to_page(pfn); /* * The HWPoisoned page may be not in buddy system, and * page_count() is not 0. */ if (unlikely(!PageBuddy(page) PageHWPoison(page))) { pfn; continue; } /* * At this point all remaining PageOffline() pages have a * reference count of 0 and can simply be skipped. */ if (PageOffline(page)) { BUG_ON(page_count(page)); BUG_ON(PageBuddy(page)); already_offline; pfn; continue; } BUG_ON(!PageBuddy(page)); VM_WARN_ON(get_pageblock_migratetype(page) ! MIGRATE_ISOLATE); order buddy_order(page); del_page_from_free_list(page, zone, order, MIGRATE_ISOLATE); pfn (1 order); } spin_unlock_irqrestore(zone-lock, flags); return end_pfn - start_pfn - already_offline; }关键处理逻辑1. 跳过硬件毒化页if (unlikely(!PageBuddy(page) PageHWPoison(page))) { pfn; continue; }硬件毒化页HWPoison可能不在伙伴系统中且引用计数不为 0无法通过常规方式移除因此逐页跳过。2. 跳过已离线页if (PageOffline(page)) { BUG_ON(page_count(page)); BUG_ON(PageBuddy(page)); already_offline; pfn; continue; }PageOffline页已被标记为离线引用计数为 0不在伙伴系统中直接跳过并计数。3. 从伙伴系统摘除空闲页BUG_ON(!PageBuddy(page)); VM_WARN_ON(get_pageblock_migratetype(page) ! MIGRATE_ISOLATE); order buddy_order(page); del_page_from_free_list(page, zone, order, MIGRATE_ISOLATE); pfn (1 order);断言页面确实是 Buddy 状态否则说明隔离不彻底。调试模式下警告迁移类型必须为MIGRATE_ISOLATE。用buddy_order(page)获取页块阶数然后整体从空闲链表中摘除。4. 返回值return end_pfn - start_pfn - already_offline;返回实际移除的“被管理页”数量供调用方adjust_managed_page_count()更新 zone 统计。关键约束必须跨完整 section注释要求范围必须 span full sections。必须先隔离调用前必须通过start_isolate_page_range()将 pageblock 标记为MIGRATE_ISOLATE。必须在zone-lock下操作摘除空闲链表需要持有 zone 锁。与调用方的关系在offline_pages()流程中__offline_isolated_pages()在test_pages_isolated()确认全部隔离成功后调用。它移除页后调用方会修正zone-nr_isolate_pageblock计数。调用zone_pcp_enable(zone)恢复 PCP 缓存。用adjust_managed_page_count()更新统计。清空节点状态并重建 zonelist。2026 年的重构2026 年的补丁将其中的显式spin_lock_irqsave/spin_unlock_irqrestore替换为guard(spinlock_irqsave)作用域锁简化了错误路径的锁管理。