N_MEMORY fallback lists should not include N_MEMORY_PRIVATE nodes, at worst this would allow allocation from them in some scenarios, and at best it causes iterations over nodes that aren't eligible.
Private node primary fallback lists do include N_MEMORY nodes so kernel/slab allocations made on behalf of the private node can fall back to DRAM when __GFP_PRIVATE is not set. The nofallback list contains only the node's own zones, restricting __GFP_THISNODE allocations to the private node. Signed-off-by: Gregory Price <[email protected]> --- mm/page_alloc.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 47f2619d3840..5a1b35421d78 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -5683,6 +5683,26 @@ static void build_zonelists(pg_data_t *pgdat) local_node = pgdat->node_id; prev_node = local_node; + /* + * Private nodes need N_MEMORY nodes as fallback for kernel allocations + * (e.g., slab objects allocated on behalf of this node). + */ + if (node_state(local_node, N_MEMORY_PRIVATE)) { + node_order[nr_nodes++] = local_node; + node_set(local_node, used_mask); + + while ((node = find_next_best_node(local_node, &used_mask)) >= 0) + node_order[nr_nodes++] = node; + + build_zonelists_in_node_order(pgdat, node_order, nr_nodes); + build_thisnode_zonelists(pgdat); + pr_info("Fallback order for Node %d (private):", local_node); + for (node = 0; node < nr_nodes; node++) + pr_cont(" %d", node_order[node]); + pr_cont("\n"); + return; + } + memset(node_order, 0, sizeof(node_order)); while ((node = find_next_best_node(local_node, &used_mask)) >= 0) { /* -- 2.53.0
