diff options
-rw-r--r-- | include/linux/memory_hotplug.h | 1 | ||||
-rw-r--r-- | mm/memory_hotplug.c | 28 |
2 files changed, 29 insertions, 0 deletions
diff --git a/include/linux/memory_hotplug.h b/include/linux/memory_hotplug.h index 79dd9eca054f..d9524c49d767 100644 --- a/include/linux/memory_hotplug.h +++ b/include/linux/memory_hotplug.h | |||
@@ -259,6 +259,7 @@ static inline void remove_memory(int nid, u64 start, u64 size) {} | |||
259 | extern int walk_memory_range(unsigned long start_pfn, unsigned long end_pfn, | 259 | extern int walk_memory_range(unsigned long start_pfn, unsigned long end_pfn, |
260 | void *arg, int (*func)(struct memory_block *, void *)); | 260 | void *arg, int (*func)(struct memory_block *, void *)); |
261 | extern int add_memory(int nid, u64 start, u64 size); | 261 | extern int add_memory(int nid, u64 start, u64 size); |
262 | extern int zone_for_memory(int nid, u64 start, u64 size, int zone_default); | ||
262 | extern int arch_add_memory(int nid, u64 start, u64 size); | 263 | extern int arch_add_memory(int nid, u64 start, u64 size); |
263 | extern int offline_pages(unsigned long start_pfn, unsigned long nr_pages); | 264 | extern int offline_pages(unsigned long start_pfn, unsigned long nr_pages); |
264 | extern bool is_memblock_offlined(struct memory_block *mem); | 265 | extern bool is_memblock_offlined(struct memory_block *mem); |
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index a3797d3fd8a4..2ff8c2325e96 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c | |||
@@ -1159,6 +1159,34 @@ static int check_hotplug_memory_range(u64 start, u64 size) | |||
1159 | return 0; | 1159 | return 0; |
1160 | } | 1160 | } |
1161 | 1161 | ||
1162 | /* | ||
1163 | * If movable zone has already been setup, newly added memory should be check. | ||
1164 | * If its address is higher than movable zone, it should be added as movable. | ||
1165 | * Without this check, movable zone may overlap with other zone. | ||
1166 | */ | ||
1167 | static int should_add_memory_movable(int nid, u64 start, u64 size) | ||
1168 | { | ||
1169 | unsigned long start_pfn = start >> PAGE_SHIFT; | ||
1170 | pg_data_t *pgdat = NODE_DATA(nid); | ||
1171 | struct zone *movable_zone = pgdat->node_zones + ZONE_MOVABLE; | ||
1172 | |||
1173 | if (zone_is_empty(movable_zone)) | ||
1174 | return 0; | ||
1175 | |||
1176 | if (movable_zone->zone_start_pfn <= start_pfn) | ||
1177 | return 1; | ||
1178 | |||
1179 | return 0; | ||
1180 | } | ||
1181 | |||
1182 | int zone_for_memory(int nid, u64 start, u64 size, int zone_default) | ||
1183 | { | ||
1184 | if (should_add_memory_movable(nid, start, size)) | ||
1185 | return ZONE_MOVABLE; | ||
1186 | |||
1187 | return zone_default; | ||
1188 | } | ||
1189 | |||
1162 | /* we are OK calling __meminit stuff here - we have CONFIG_MEMORY_HOTPLUG */ | 1190 | /* we are OK calling __meminit stuff here - we have CONFIG_MEMORY_HOTPLUG */ |
1163 | int __ref add_memory(int nid, u64 start, u64 size) | 1191 | int __ref add_memory(int nid, u64 start, u64 size) |
1164 | { | 1192 | { |