diff options
-rw-r--r-- | mm/memory_hotplug.c | 72 |
1 files changed, 15 insertions, 57 deletions
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index b1be791f772d..df570e5c71cc 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c | |||
@@ -436,67 +436,25 @@ static void shrink_zone_span(struct zone *zone, unsigned long start_pfn, | |||
436 | zone_span_writeunlock(zone); | 436 | zone_span_writeunlock(zone); |
437 | } | 437 | } |
438 | 438 | ||
439 | static void shrink_pgdat_span(struct pglist_data *pgdat, | 439 | static void update_pgdat_span(struct pglist_data *pgdat) |
440 | unsigned long start_pfn, unsigned long end_pfn) | ||
441 | { | 440 | { |
442 | unsigned long pgdat_start_pfn = pgdat->node_start_pfn; | 441 | unsigned long node_start_pfn = 0, node_end_pfn = 0; |
443 | unsigned long p = pgdat_end_pfn(pgdat); /* pgdat_end_pfn namespace clash */ | 442 | struct zone *zone; |
444 | unsigned long pgdat_end_pfn = p; | ||
445 | unsigned long pfn; | ||
446 | int nid = pgdat->node_id; | ||
447 | |||
448 | if (pgdat_start_pfn == start_pfn) { | ||
449 | /* | ||
450 | * If the section is smallest section in the pgdat, it need | ||
451 | * shrink pgdat->node_start_pfn and pgdat->node_spanned_pages. | ||
452 | * In this case, we find second smallest valid mem_section | ||
453 | * for shrinking zone. | ||
454 | */ | ||
455 | pfn = find_smallest_section_pfn(nid, NULL, end_pfn, | ||
456 | pgdat_end_pfn); | ||
457 | if (pfn) { | ||
458 | pgdat->node_start_pfn = pfn; | ||
459 | pgdat->node_spanned_pages = pgdat_end_pfn - pfn; | ||
460 | } | ||
461 | } else if (pgdat_end_pfn == end_pfn) { | ||
462 | /* | ||
463 | * If the section is biggest section in the pgdat, it need | ||
464 | * shrink pgdat->node_spanned_pages. | ||
465 | * In this case, we find second biggest valid mem_section for | ||
466 | * shrinking zone. | ||
467 | */ | ||
468 | pfn = find_biggest_section_pfn(nid, NULL, pgdat_start_pfn, | ||
469 | start_pfn); | ||
470 | if (pfn) | ||
471 | pgdat->node_spanned_pages = pfn - pgdat_start_pfn + 1; | ||
472 | } | ||
473 | |||
474 | /* | ||
475 | * If the section is not biggest or smallest mem_section in the pgdat, | ||
476 | * it only creates a hole in the pgdat. So in this case, we need not | ||
477 | * change the pgdat. | ||
478 | * But perhaps, the pgdat has only hole data. Thus it check the pgdat | ||
479 | * has only hole or not. | ||
480 | */ | ||
481 | pfn = pgdat_start_pfn; | ||
482 | for (; pfn < pgdat_end_pfn; pfn += PAGES_PER_SUBSECTION) { | ||
483 | if (unlikely(!pfn_valid(pfn))) | ||
484 | continue; | ||
485 | |||
486 | if (pfn_to_nid(pfn) != nid) | ||
487 | continue; | ||
488 | 443 | ||
489 | /* Skip range to be removed */ | 444 | for (zone = pgdat->node_zones; |
490 | if (pfn >= start_pfn && pfn < end_pfn) | 445 | zone < pgdat->node_zones + MAX_NR_ZONES; zone++) { |
491 | continue; | 446 | unsigned long zone_end_pfn = zone->zone_start_pfn + |
447 | zone->spanned_pages; | ||
492 | 448 | ||
493 | /* If we find valid section, we have nothing to do */ | 449 | /* No need to lock the zones, they can't change. */ |
494 | return; | 450 | if (zone_end_pfn > node_end_pfn) |
451 | node_end_pfn = zone_end_pfn; | ||
452 | if (zone->zone_start_pfn < node_start_pfn) | ||
453 | node_start_pfn = zone->zone_start_pfn; | ||
495 | } | 454 | } |
496 | 455 | ||
497 | /* The pgdat has no valid section */ | 456 | pgdat->node_start_pfn = node_start_pfn; |
498 | pgdat->node_start_pfn = 0; | 457 | pgdat->node_spanned_pages = node_end_pfn - node_start_pfn; |
499 | pgdat->node_spanned_pages = 0; | ||
500 | } | 458 | } |
501 | 459 | ||
502 | static void __remove_zone(struct zone *zone, unsigned long start_pfn, | 460 | static void __remove_zone(struct zone *zone, unsigned long start_pfn, |
@@ -507,7 +465,7 @@ static void __remove_zone(struct zone *zone, unsigned long start_pfn, | |||
507 | 465 | ||
508 | pgdat_resize_lock(zone->zone_pgdat, &flags); | 466 | pgdat_resize_lock(zone->zone_pgdat, &flags); |
509 | shrink_zone_span(zone, start_pfn, start_pfn + nr_pages); | 467 | shrink_zone_span(zone, start_pfn, start_pfn + nr_pages); |
510 | shrink_pgdat_span(pgdat, start_pfn, start_pfn + nr_pages); | 468 | update_pgdat_span(pgdat); |
511 | pgdat_resize_unlock(zone->zone_pgdat, &flags); | 469 | pgdat_resize_unlock(zone->zone_pgdat, &flags); |
512 | } | 470 | } |
513 | 471 | ||