summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/nodemask.h10
-rw-r--r--mm/memory_hotplug.c7
-rw-r--r--mm/page_alloc.c25
3 files changed, 35 insertions, 7 deletions
diff --git a/include/linux/nodemask.h b/include/linux/nodemask.h
index 583e6b843d2a..ccee962f3559 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 df9d554bea30..9c12ae5e3695 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 0cc5b3e198e5..07dfd89992fa 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;
}