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 | } |
