diff options
Diffstat (limited to 'mm/memory_hotplug.c')
-rw-r--r-- | mm/memory_hotplug.c | 48 |
1 files changed, 18 insertions, 30 deletions
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index d4e940a26945..9260314a221e 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c | |||
@@ -602,27 +602,14 @@ static struct page *next_active_pageblock(struct page *page) | |||
602 | /* Checks if this range of memory is likely to be hot-removable. */ | 602 | /* Checks if this range of memory is likely to be hot-removable. */ |
603 | int is_mem_section_removable(unsigned long start_pfn, unsigned long nr_pages) | 603 | int is_mem_section_removable(unsigned long start_pfn, unsigned long nr_pages) |
604 | { | 604 | { |
605 | int type; | ||
606 | struct page *page = pfn_to_page(start_pfn); | 605 | struct page *page = pfn_to_page(start_pfn); |
607 | struct page *end_page = page + nr_pages; | 606 | struct page *end_page = page + nr_pages; |
608 | 607 | ||
609 | /* Check the starting page of each pageblock within the range */ | 608 | /* Check the starting page of each pageblock within the range */ |
610 | for (; page < end_page; page = next_active_pageblock(page)) { | 609 | for (; page < end_page; page = next_active_pageblock(page)) { |
611 | type = get_pageblock_migratetype(page); | 610 | if (!is_pageblock_removable_nolock(page)) |
612 | |||
613 | /* | ||
614 | * A pageblock containing MOVABLE or free pages is considered | ||
615 | * removable | ||
616 | */ | ||
617 | if (type != MIGRATE_MOVABLE && !pageblock_free(page)) | ||
618 | return 0; | ||
619 | |||
620 | /* | ||
621 | * A pageblock starting with a PageReserved page is not | ||
622 | * considered removable. | ||
623 | */ | ||
624 | if (PageReserved(page)) | ||
625 | return 0; | 611 | return 0; |
612 | cond_resched(); | ||
626 | } | 613 | } |
627 | 614 | ||
628 | /* All pageblocks in the memory block are likely to be hot-removable */ | 615 | /* All pageblocks in the memory block are likely to be hot-removable */ |
@@ -659,7 +646,7 @@ static int test_pages_in_a_zone(unsigned long start_pfn, unsigned long end_pfn) | |||
659 | * Scanning pfn is much easier than scanning lru list. | 646 | * Scanning pfn is much easier than scanning lru list. |
660 | * Scan pfn from start to end and Find LRU page. | 647 | * Scan pfn from start to end and Find LRU page. |
661 | */ | 648 | */ |
662 | int scan_lru_pages(unsigned long start, unsigned long end) | 649 | static unsigned long scan_lru_pages(unsigned long start, unsigned long end) |
663 | { | 650 | { |
664 | unsigned long pfn; | 651 | unsigned long pfn; |
665 | struct page *page; | 652 | struct page *page; |
@@ -709,29 +696,30 @@ do_migrate_range(unsigned long start_pfn, unsigned long end_pfn) | |||
709 | page_is_file_cache(page)); | 696 | page_is_file_cache(page)); |
710 | 697 | ||
711 | } else { | 698 | } else { |
712 | /* Becasue we don't have big zone->lock. we should | ||
713 | check this again here. */ | ||
714 | if (page_count(page)) | ||
715 | not_managed++; | ||
716 | #ifdef CONFIG_DEBUG_VM | 699 | #ifdef CONFIG_DEBUG_VM |
717 | printk(KERN_ALERT "removing pfn %lx from LRU failed\n", | 700 | printk(KERN_ALERT "removing pfn %lx from LRU failed\n", |
718 | pfn); | 701 | pfn); |
719 | dump_page(page); | 702 | dump_page(page); |
720 | #endif | 703 | #endif |
704 | /* Becasue we don't have big zone->lock. we should | ||
705 | check this again here. */ | ||
706 | if (page_count(page)) { | ||
707 | not_managed++; | ||
708 | ret = -EBUSY; | ||
709 | break; | ||
710 | } | ||
721 | } | 711 | } |
722 | } | 712 | } |
723 | ret = -EBUSY; | 713 | if (!list_empty(&source)) { |
724 | if (not_managed) { | 714 | if (not_managed) { |
725 | if (!list_empty(&source)) | 715 | putback_lru_pages(&source); |
716 | goto out; | ||
717 | } | ||
718 | /* this function returns # of failed pages */ | ||
719 | ret = migrate_pages(&source, hotremove_migrate_alloc, 0, 1); | ||
720 | if (ret) | ||
726 | putback_lru_pages(&source); | 721 | putback_lru_pages(&source); |
727 | goto out; | ||
728 | } | 722 | } |
729 | ret = 0; | ||
730 | if (list_empty(&source)) | ||
731 | goto out; | ||
732 | /* this function returns # of failed pages */ | ||
733 | ret = migrate_pages(&source, hotremove_migrate_alloc, 0, 1); | ||
734 | |||
735 | out: | 723 | out: |
736 | return ret; | 724 | return ret; |
737 | } | 725 | } |