From a5cbf5fc46a5ee2b8e4443d82ad6ff9b4628ea43 Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Tue, 16 Oct 2007 01:25:29 -0700 Subject: [PATCH] Memoryless nodes: introduce mask of nodes with memory 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. [akpm@linux-foundation.org: build fix] [Lee.Schermerhorn@hp.com: update N_HIGH_MEMORY node state for memory hotadd] [y-goto@jp.fujitsu.com: Fix memory hotplug + sparsemem build] 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: Yasunori Goto Signed-off-by: Paul Mundt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/nodemask.h | 10 ++++++++-- mm/memory_hotplug.c | 7 ++++--- mm/page_alloc.c | 25 +++++++++++++++++++++++-- 3 files changed, 35 insertions(+), 7 deletions(-) diff --git a/include/linux/nodemask.h b/include/linux/nodemask.h index 583e6b843d2a8..ccee962f3559b 100644 --- a/include/linux/nodemask.h +++ b/include/linux/nodemask.h @@ -341,8 +341,14 @@ static inline void __nodes_remap(nodemask_t *dstp, const nodemask_t *srcp, * 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 --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index df9d554bea308..9c12ae5e3695a 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c @@ -217,6 +217,10 @@ int online_pages(unsigned long pfn, unsigned long nr_pages) zone->zone_pgdat->node_present_pages += onlined_pages; setup_per_zone_pages_min(); + if (onlined_pages) { + kswapd_run(zone_to_nid(zone)); + node_set_state(zone_to_nid(zone), N_HIGH_MEMORY); + } if (need_zonelists_rebuild) build_all_zonelists(); @@ -271,9 +275,6 @@ int add_memory(int nid, u64 start, u64 size) if (!pgdat) return -ENOMEM; new_pgdat = 1; - ret = kswapd_run(nid); - if (ret) - goto error; } /* call arch's memory hotadd */ diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 0cc5b3e198e5e..07dfd89992fa6 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -2080,14 +2080,35 @@ static void build_zonelist_cache(pg_data_t *pgdat) #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_type; + + for (zone_type = 0; zone_type <= ZONE_NORMAL; zone_type++) { + struct zone *zone = &pgdat->node_zones[zone_type]; + if (zone->present_pages) + node_set_state(zone_to_nid(zone), 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; } -- 2.39.5