free_area_init_memoryless_node(nid);
That's really just free_area_init_node() below, I do wonder what value free_area_init_memoryless_node() has as of today.
I am not sure there is any real value in having this special name for this but I have kept is sync with what x86 does currently. If we want to remove the wrapper then just do it everywhere. I can do that on top.
Sure, just a general comment.
continue;
}
- free_area_init_node(nid);
/* Any memory on that node */
Could you give it a try? I do not have any machine which would exhibit the problem so I cannot really test this out. I hope build_zone_info will not choke on this. I assume the node distance table is uninitialized for these nodes and IIUC this should lead to an assumption that all other nodes are close. But who knows that can blow up there.
Btw. does this make any sense at all to others?
__build_all_zonelists() has to update the zonelists of all nodes I think.
I am not sure what you mean. This should be achieved by this patch because the boot time build_all_zonelists will go over all online nodes
"Over all possible nodes", including online and offline ones, to make sure any possible node has a valid pgdat. IIUC, you're not changing anything about online vs offline nodes, only that we have a pgdat also for offline nodes.
(i.e. with pgdat). free_area_init happens before that. I am just worried that the arch specific node_distance() will generate a complete garbage or blow up for some reason.
Assume you online a new zone and then call __build_all_zonelists() to include the zone in all zonelists (via online_pages()). __build_all_zonelists() will not include offline nodes (that still have a pgdat with a valid zonelist now).
Similarly, assume you online a zone and then call __build_all_zonelists() to exclude the zone from all zonelists (via offline_pages()). __build_all_zonelists() will not include offline nodes (that still have a pgdat with a valid zonelist now).
Essentially, IIRC, even after your change start_kernel()->build_all_zonelists(NULL)->build_all_zonelists_init()->__build_all_zonelists(NULL) won't initialize the zonelist of the new pgdat, because the nodes are offline.
I'd assume we'd need
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index c5952749ad40..e5d958abc7cc 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -6382,7 +6382,7 @@ static void __build_all_zonelists(void *data) if (self && !node_online(self->node_id)) { build_zonelists(self); } else { - for_each_online_node(nid) { + for_each_node(nid) { pg_data_t *pgdat = NODE_DATA(nid);
build_zonelists(pgdat);
to properly initialize the zonelist also for the offline nodes with a valid pgdat.
But maybe I am missing something important regarding online vs. offline nodes that your patch changes?