build_thisnode_zonelists()是用于构建仅本节点thisnode-onlyzonelist的函数。它服务于那些严格限定只能从本地节点分配的场景最典型的用途是GFP_THISNODE分配。核心作用与背景在 NUMA 系统中普通的分配允许在本地节点内存不足时回退到远程节点。但有些调用方如alloc_pages_node()配合__GFP_THISNODE明确要求只能从指定节点分配不允许跨节点回退。为了高效支持这种需求内核为每个节点维护了两套 zonelistzonelist用途ZONELIST_FALLBACK普通分配允许回退到远程节点ZONELIST_NOFALLBACK严格本节点分配__GFP_THISNODE不允许回退build_thisnode_zonelists()负责构建后者。核心实现static void build_thisnode_zonelists(pg_data_t *pgdat) { struct zoneref *zonerefs; int nr_zones; zonerefs pgdat-node_zonelists[ZONELIST_NOFALLBACK]._zonerefs; nr_zones build_zonerefs_node(pgdat, zonerefs); zonerefs nr_zones; zonerefs-zone NULL; zonerefs-zone_idx 0; }逻辑解析1. 获取目标 zonelistzonerefs pgdat-node_zonelists[ZONELIST_NOFALLBACK]._zonerefs;定位到本节点的ZONELIST_NOFALLBACK数组。2. 只构建本节点的 zonenr_zones build_zonerefs_node(pgdat, zonerefs);调用build_zonerefs_node()前面讲过的只把pgdat自己的 zone填入zonerefs返回 zone 数量。3. NULL 终止zonerefs nr_zones; zonerefs-zone NULL; zonerefs-zone_idx 0;在末尾写入 NULL标记 zonelist 结束。与build_zonelists_in_node_order()的对比方面build_zonelists_in_node_order()build_thisnode_zonelists()目标 zonelistZONELIST_FALLBACKZONELIST_NOFALLBACK包含节点本地 所有远程节点仅本地节点循环遍历node_order[]只调一次build_zonerefs_node()用途普通分配可回退__GFP_THISNODE严格分配在初始化流程中的位置它被build_zonelists()调用与build_zonelists_in_node_order()或build_zonelists_in_zone_order()并列static void build_zonelists(pg_data_t *pgdat) { ... if (zonelist_order ZONELIST_ORDER_NODE) build_zonelists_in_node_order(pgdat, node_order, nr_nodes); else build_zonelists_in_zone_order(pgdat, nr_nodes); build_thisnode_zonelists(pgdat); }即无论采用哪种排序策略都会额外构建一套thisnodezonelist。为什么需要独立的thisnodezonelist1. 性能如果每次__GFP_THISNODE分配都从完整的 fallback zonelist 中过滤出本地节点开销较大。预构建一个只含本地 zone 的 zonelist分配时直接遍历效率更高。2. 语义清晰__GFP_THISNODE的语义是“严格只从指定节点分配失败也不回退”。独立的 zonelist 明确表达了这一约束避免了在 fallback 列表中误用远程 zone 的风险。3. 正确的行为对于__GFP_THISNODE如果本地节点无法满足分配应该直接失败而不是回退到远程节点。独立的ZONELIST_NOFALLBACK保证了这一点。使用场景ZONELIST_NOFALLBACK主要在__alloc_pages_noprof()路径中当gfp_mask包含__GFP_THISNODE时被选用if (gfp_mask __GFP_THISNODE) ac-zonelist NODE_DATA(preferred_nid)-node_zonelists[ZONELIST_NOFALLBACK]; else ac-zonelist node_zonelist(preferred_nid, gfp_mask);总结build_thisnode_zonelists()是ZONELIST_NOFALLBACK的构建器它只把本节点的 zone 填入该 zonelist 并用 NULL 终止为__GFP_THISNODE严格本节点分配提供高效的查找结构。它与build_zonelists_in_node_order()/build_zonelists_in_zone_order()并列在每次build_zonelists()时都会被调用确保每个节点都同时拥有“可回退”和“不可回退”两套分配列表。
阅读完成 · 觉得有帮助?