page_alloc fallbacks[][]
伙伴系统中迁移类型降级fallback的优先级表。当某种迁移类型的空闲链表耗尽时分配器按这个表尝试从其他类型偷页。一、背景为什么需要 fallback迁移类型与反碎片空闲页按迁移类型分组MIGRATE_UNMOVABLE/MOVABLE/RECLAIMABLE等。分配时优先从同类型链表取页保持同类页聚集减少碎片。__rmqueue_smallest()负责同类型分配。问题同类型耗尽怎么办如果请求MIGRATE_UNMOVABLE但MIGRATE_UNMOVABLE链表空了不能直接失败——那会导致分配失败、系统不可用。必须允许从其他迁移类型借用页块。但借用会破坏反碎片把可移动页块借给不可移动用途混合后难以整块迁移/回收。解决有策略的 fallback不随便借而是按预定义的优先级尝试。优先借影响最小的类型。这就是fallbacks[][]数组的作用。二、数组定义解析static int fallbacks[MIGRATE_PCPTYPES][MIGRATE_PCPTYPES - 1] { [MIGRATE_UNMOVABLE] { MIGRATE_RECLAIMABLE, MIGRATE_MOVABLE }, [MIGRATE_MOVABLE] { MIGRATE_RECLAIMABLE, MIGRATE_UNMOVABLE }, [MIGRATE_RECLAIMABLE] { MIGRATE_UNMOVABLE, MIGRATE_MOVABLE }, };1. 维度[MIGRATE_PCPTYPES][MIGRATE_PCPTYPES - 1]第一维请求的迁移类型MIGRATE_PCPTYPES种即参与 PCP/分组的前几种。第二维候选的 fallback 类型列表长度为MIGRATE_PCPTYPES - 1排除自己。用指定初始化器[MIGRATE_UNMOVABLE] {...}清晰对应每种类型。2. 注释/* * This array describes the order lists are fallen back to when * the free lists for the desirable migrate type are depleted * * The other migratetypes do not have fallbacks. */the order lists are fallen back to当目标类型链表耗尽时按此顺序尝试其他类型。The other migratetypes do not have fallbacksCMA、ISOLATE等不参与 fallbackMIGRATE_CMACMA 区域有特殊用途不能被普通分配随意借用但可反向普通类型可借 CMA实际有特殊处理MIGRATE_ISOLATE隔离区绝对不能借用。所以数组第一维只覆盖MIGRATE_PCPTYPES。3. 三行内容请求类型第一优先 fallback第二优先 fallbackMIGRATE_UNMOVABLEMIGRATE_RECLAIMABLEMIGRATE_MOVABLEMIGRATE_MOVABLEMIGRATE_RECLAIMABLEMIGRATE_UNMOVABLEMIGRATE_RECLAIMABLEMIGRATE_UNMOVABLEMIGRATE_MOVABLE三、优先级的设计逻辑核心原则借影响最小的类型不同迁移类型的可移动性不同MIGRATE_MOVABLE可移动用户态页最灵活可迁移/回收。MIGRATE_RECLAIMABLE可回收slab 缓存可回收但不可迁移。MIGRATE_UNMOVABLE不可移动内核结构既不可迁移也不可回收最死。破坏顺序从轻到重借RECLAIMABLE最坏情况是回收页块仍可能恢复借MOVABLE可迁移但可能造成碎片借UNMOVABLE最糟糕永久占据破坏连续性。逐行分析MIGRATE_UNMOVABLE的 fallback[MIGRATE_UNMOVABLE] { MIGRATE_RECLAIMABLE, MIGRATE_MOVABLE },请求不可移动页但不可移动链表空了。优先借RECLAIMABLE可回收未来能还回来再借MOVABLE可迁移影响次之最后才考虑虽然表里只列了两个实际逻辑可能还有更多处理。不会借UNMOVABLE自己因为已经空了。MIGRATE_MOVABLE的 fallback[MIGRATE_MOVABLE] { MIGRATE_RECLAIMABLE, MIGRATE_UNMOVABLE },请求可移动页但可移动链表空了。优先借RECLAIMABLE可回收再借UNMOVABLE不可移动但至少能用顺序反映宁可借不可移动也不……这里没有更多选项。MIGRATE_RECLAIMABLE的 fallback[MIGRATE_RECLAIMABLE] { MIGRATE_UNMOVABLE, MIGRATE_MOVABLE },请求可回收页但可回收链表空了。优先借UNMOVABLE不可移动但稳定再借MOVABLE可移动为什么优先UNMOVABLE因为 RECLAIMABLE 本身不可迁移借UNMOVABLE语义更接近都不可迁移借MOVABLE反而可能把可移动页块污染成不可回收用途。设计哲学总结尽量借能还回来的类型RECLAIMABLE优先可回收其次借影响小的类型避免借不可逆的类型除非别无选择。四、在 fallback 路径中的使用__rmqueue_fallback()static inline struct page *__rmqueue_fallback(struct zone *zone, int order, int start_migratetype, unsigned int alloc_flags) { int current_order, i; struct page *page; struct free_area *area; int migratetype; int fallback_mt; /* * 从最高阶往下找找能拆出 order 的块 */ for (current_order MAX_ORDER - 1; current_order order; --current_order) { area zone-free_area[current_order]; /* * 按 fallbacks 数组顺序尝试其他迁移类型 */ for (i 0; i MIGRATE_PCPTYPES - 1; i) { fallback_mt fallbacks[start_migratetype][i]; /* 跳过被隔离的类型 */ if (is_migrate_isolate(fallback_mt)) continue; /* 尝试从该类型取页 */ page get_page_from_free_area(area, fallback_mt); if (!page) continue; /* 找到取走并拆分 */ del_page_from_free_list(page, zone, current_order, fallback_mt); ... /* * 把该 pageblock 的迁移类型改为请求类型 * 或做其他反碎片处理 */ ... return page; } } return NULL; }关键点按fallbacks[start_migratetype]顺序尝试i 0第一优先 fallbacki 1第二优先依次尝试。跳过隔离类型is_migrate_isolate(fallback_mt)检查隔离区不能借。借用后可能改变迁移类型把借来的 pageblock 标记为请求类型反映实际用途或做其他反碎片处理如判断是否值得偷整个 pageblock。从高阶往下找优先用高阶块可以拆分成多个小块更灵活避免把小块的连续性破坏。五、与前面内容的呼应前面出现过的这里的关联migratetype_names[]MIGRATE_*的名字表__rmqueue_smallest()同类型分配失败后走 fallback__rmqueue_fallback()使用fallbacks[][]表MIGRATE_PCPTYPES数组第一维大小is_migrate_isolate()跳过隔离类型MIGRATE_CMA/MIGRATE_ISOLATE不参与 fallbackset_pageblock_migratetype()借用后可能更新类型反碎片fallback 策略的核心目标调用链__rmqueue() ├── __rmqueue_smallest() // 同类型 └── if (!page) __rmqueue_fallback() // 跨类型 └── for (i 0; i MIGRATE_PCPTYPES - 1; i) fallback_mt fallbacks[start_migratetype][i] ...六、小结表项说明数组名fallbacks维度[MIGRATE_PCPTYPES][MIGRATE_PCPTYPES - 1]作用定义各迁移类型的降级借用优先级第一维请求的迁移类型第二维候选 fallback 类型按优先级排列不参与的类型CMA、ISOLATEThe other migratetypes do not have fallbacks设计原则优先借可回收/影响小的类型使用点__rmqueue_fallback()可见性static文件内私有三行速查请求类型优先借其次借UNMOVABLERECLAIMABLEMOVABLEMOVABLERECLAIMABLEUNMOVABLERECLAIMABLEUNMOVABLEMOVABLE一句话总结fallbacks[][]定义了伙伴系统中迁移类型的降级借用优先级当请求类型的空闲链表耗尽时按此表依次尝试从其他类型偷页它只覆盖MIGRATE_PCPTYPES三种类型CMA/ISOLATE不参与设计原则是优先借可回收、影响小的类型如RECLAIMABLE以尽量减少对反碎片的破坏。