aboutsummaryrefslogtreecommitdiffstats
path: root/mm/memory_hotplug.c
diff options
context:
space:
mode:
authorLai Jiangshan <laijs@cn.fujitsu.com>2012-12-11 19:03:20 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2012-12-11 20:22:28 -0500
commite455a9b92d6e19a3f0f7eb6f6241efa566a7e81a (patch)
treef920832f9e55ecf3e178e498f8894363748bb6c7 /mm/memory_hotplug.c
parent511c2aba8f07fc45bdcba548cb63f7b8a450c6dc (diff)
memory_hotplug: handle empty zone when online_movable/online_kernel
Make online_movable/online_kernel can empty a zone or can move memory to a empty zone. Signed-off-by: Lai Jiangshan <laijs@cn.fujitsu.com> Signed-off-by: Wen Congyang <wency@cn.fujitsu.com> Cc: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com> Cc: Lai Jiangshan <laijs@cn.fujitsu.com> Cc: Jiang Liu <jiang.liu@huawei.com> Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com> Cc: Minchan Kim <minchan.kim@gmail.com> Cc: Mel Gorman <mgorman@suse.de> Cc: David Rientjes <rientjes@google.com> Cc: Yinghai Lu <yinghai@kernel.org> Cc: Rusty Russell <rusty@rustcorp.com.au> Cc: Greg KH <greg@kroah.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/memory_hotplug.c')
-rw-r--r--mm/memory_hotplug.c51
1 files changed, 45 insertions, 6 deletions
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index 5c1f4959e6b4..c370491bdb97 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -219,8 +219,17 @@ static void resize_zone(struct zone *zone, unsigned long start_pfn,
219{ 219{
220 zone_span_writelock(zone); 220 zone_span_writelock(zone);
221 221
222 zone->zone_start_pfn = start_pfn; 222 if (end_pfn - start_pfn) {
223 zone->spanned_pages = end_pfn - start_pfn; 223 zone->zone_start_pfn = start_pfn;
224 zone->spanned_pages = end_pfn - start_pfn;
225 } else {
226 /*
227 * make it consist as free_area_init_core(),
228 * if spanned_pages = 0, then keep start_pfn = 0
229 */
230 zone->zone_start_pfn = 0;
231 zone->spanned_pages = 0;
232 }
224 233
225 zone_span_writeunlock(zone); 234 zone_span_writeunlock(zone);
226} 235}
@@ -236,10 +245,19 @@ static void fix_zone_id(struct zone *zone, unsigned long start_pfn,
236 set_page_links(pfn_to_page(pfn), zid, nid, pfn); 245 set_page_links(pfn_to_page(pfn), zid, nid, pfn);
237} 246}
238 247
239static int move_pfn_range_left(struct zone *z1, struct zone *z2, 248static int __meminit move_pfn_range_left(struct zone *z1, struct zone *z2,
240 unsigned long start_pfn, unsigned long end_pfn) 249 unsigned long start_pfn, unsigned long end_pfn)
241{ 250{
251 int ret;
242 unsigned long flags; 252 unsigned long flags;
253 unsigned long z1_start_pfn;
254
255 if (!z1->wait_table) {
256 ret = init_currently_empty_zone(z1, start_pfn,
257 end_pfn - start_pfn, MEMMAP_HOTPLUG);
258 if (ret)
259 return ret;
260 }
243 261
244 pgdat_resize_lock(z1->zone_pgdat, &flags); 262 pgdat_resize_lock(z1->zone_pgdat, &flags);
245 263
@@ -253,7 +271,13 @@ static int move_pfn_range_left(struct zone *z1, struct zone *z2,
253 if (end_pfn <= z2->zone_start_pfn) 271 if (end_pfn <= z2->zone_start_pfn)
254 goto out_fail; 272 goto out_fail;
255 273
256 resize_zone(z1, z1->zone_start_pfn, end_pfn); 274 /* use start_pfn for z1's start_pfn if z1 is empty */
275 if (z1->spanned_pages)
276 z1_start_pfn = z1->zone_start_pfn;
277 else
278 z1_start_pfn = start_pfn;
279
280 resize_zone(z1, z1_start_pfn, end_pfn);
257 resize_zone(z2, end_pfn, z2->zone_start_pfn + z2->spanned_pages); 281 resize_zone(z2, end_pfn, z2->zone_start_pfn + z2->spanned_pages);
258 282
259 pgdat_resize_unlock(z1->zone_pgdat, &flags); 283 pgdat_resize_unlock(z1->zone_pgdat, &flags);
@@ -266,10 +290,19 @@ out_fail:
266 return -1; 290 return -1;
267} 291}
268 292
269static int move_pfn_range_right(struct zone *z1, struct zone *z2, 293static int __meminit move_pfn_range_right(struct zone *z1, struct zone *z2,
270 unsigned long start_pfn, unsigned long end_pfn) 294 unsigned long start_pfn, unsigned long end_pfn)
271{ 295{
296 int ret;
272 unsigned long flags; 297 unsigned long flags;
298 unsigned long z2_end_pfn;
299
300 if (!z2->wait_table) {
301 ret = init_currently_empty_zone(z2, start_pfn,
302 end_pfn - start_pfn, MEMMAP_HOTPLUG);
303 if (ret)
304 return ret;
305 }
273 306
274 pgdat_resize_lock(z1->zone_pgdat, &flags); 307 pgdat_resize_lock(z1->zone_pgdat, &flags);
275 308
@@ -283,8 +316,14 @@ static int move_pfn_range_right(struct zone *z1, struct zone *z2,
283 if (start_pfn >= z1->zone_start_pfn + z1->spanned_pages) 316 if (start_pfn >= z1->zone_start_pfn + z1->spanned_pages)
284 goto out_fail; 317 goto out_fail;
285 318
319 /* use end_pfn for z2's end_pfn if z2 is empty */
320 if (z2->spanned_pages)
321 z2_end_pfn = z2->zone_start_pfn + z2->spanned_pages;
322 else
323 z2_end_pfn = end_pfn;
324
286 resize_zone(z1, z1->zone_start_pfn, start_pfn); 325 resize_zone(z1, z1->zone_start_pfn, start_pfn);
287 resize_zone(z2, start_pfn, z2->zone_start_pfn + z2->spanned_pages); 326 resize_zone(z2, start_pfn, z2_end_pfn);
288 327
289 pgdat_resize_unlock(z1->zone_pgdat, &flags); 328 pgdat_resize_unlock(z1->zone_pgdat, &flags);
290 329