diff --git a/include/linux/nodemask.h b/include/linux/nodemask.h index 583e6b843d2a86f5094c25932f90ea1c3b1621ff..ccee962f3559b6e97e7e8243439091dc2b9e080d 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 df9d554bea3081ec75b45e828326e015b62c0338..9c12ae5e3695af07d44b9d60fe3782fdb16903a5 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 0cc5b3e198e5e2ccab5b97846e80a1894f20ccca..07dfd89992fa6d0ee90cf0ca6646a43d7dd926e2 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; }