From: Christoph Lameter It is necessary to know if nodes have memory since we have recently begun to add support for memoryless nodes. For that purpose we introduce a two new node states: N_HIGH_MEMORY and N_NORMAL_MEMORY. A node has its bit in N_HIGH_MEMORY set if it has any memory regardless of the type of mmemory. If a node has memory then it has at least one zone defined in its pgdat structure that is located in the pgdat itself. A node has its bit in N_NORMAL_MEMORY set if it has a lower zone than ZONE_HIGHMEM. This means it is possible to allocate memory that is not subject to kmap. N_HIGH_MEMORY and N_NORMAL_MEMORY can then be used in various places to insure that we do the right thing when we encounter a memoryless node. Signed-off-by: Lee Schermerhorn Signed-off-by: Nishanth Aravamudan Signed-off-by: Christoph Lameter Acked-by: Bob Picco Cc: KAMEZAWA Hiroyuki Cc: Mel Gorman Signed-off-by: Andrew Morton --- include/linux/nodemask.h | 10 ++++++++-- mm/page_alloc.c | 24 ++++++++++++++++++++++-- 2 files changed, 30 insertions(+), 4 deletions(-) diff -puN include/linux/nodemask.h~memoryless-nodes-introduce-mask-of-nodes-with-memory include/linux/nodemask.h --- a/include/linux/nodemask.h~memoryless-nodes-introduce-mask-of-nodes-with-memory +++ a/include/linux/nodemask.h @@ -341,8 +341,14 @@ static inline void __nodes_remap(nodemas * Bitmasks that are kept for all the nodes. */ enum node_states { - N_POSSIBLE, /* The node could become online at some point */ - N_ONLINE, /* The node is online */ + N_POSSIBLE, /* The node could become online at some point */ + N_ONLINE, /* The node is online */ + N_NORMAL_MEMORY, /* The node has regular memory */ +#ifdef CONFIG_HIGHMEM + N_HIGH_MEMORY, /* The node has regular or high memory */ +#else + N_HIGH_MEMORY = N_NORMAL_MEMORY, +#endif NR_NODE_STATES }; diff -puN mm/page_alloc.c~memoryless-nodes-introduce-mask-of-nodes-with-memory mm/page_alloc.c --- a/mm/page_alloc.c~memoryless-nodes-introduce-mask-of-nodes-with-memory +++ a/mm/page_alloc.c @@ -2080,14 +2080,34 @@ static void build_zonelist_cache(pg_data #endif /* CONFIG_NUMA */ +/* Any regular memory on that node ? */ +static void check_for_regular_memory(pg_data_t *pgdat) +{ +#ifdef CONFIG_HIGHMEM + enum zone_type zone; + + for (zone = 0; zone <= ZONE_NORMAL; zone++) + if (pgdat->node_zones[zone].present_pages) + node_set_state(nid, N_NORMAL_MEMORY); + } +#endif +} + /* return values int ....just for stop_machine_run() */ static int __build_all_zonelists(void *dummy) { int nid; for_each_online_node(nid) { - build_zonelists(NODE_DATA(nid)); - build_zonelist_cache(NODE_DATA(nid)); + pg_data_t *pgdat = NODE_DATA(nid); + + build_zonelists(pgdat); + build_zonelist_cache(pgdat); + + /* Any memory on that node */ + if (pgdat->node_present_pages) + node_set_state(nid, N_HIGH_MEMORY); + check_for_regular_memory(pgdat); } return 0; } _