aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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