diff options
| -rw-r--r-- | include/linux/gfp.h | 3 | ||||
| -rw-r--r-- | include/linux/page-isolation.h | 18 | ||||
| -rw-r--r-- | mm/memory-failure.c | 2 | ||||
| -rw-r--r-- | mm/memory_hotplug.c | 6 | ||||
| -rw-r--r-- | mm/page_alloc.c | 17 | ||||
| -rw-r--r-- | mm/page_isolation.c | 15 |
6 files changed, 34 insertions, 27 deletions
diff --git a/include/linux/gfp.h b/include/linux/gfp.h index 78d32a7be257..1e49be49d324 100644 --- a/include/linux/gfp.h +++ b/include/linux/gfp.h | |||
| @@ -394,7 +394,8 @@ static inline bool pm_suspended_storage(void) | |||
| 394 | #ifdef CONFIG_CMA | 394 | #ifdef CONFIG_CMA |
| 395 | 395 | ||
| 396 | /* The below functions must be run on a range from a single zone. */ | 396 | /* The below functions must be run on a range from a single zone. */ |
| 397 | extern int alloc_contig_range(unsigned long start, unsigned long end); | 397 | extern int alloc_contig_range(unsigned long start, unsigned long end, |
| 398 | unsigned migratetype); | ||
| 398 | extern void free_contig_range(unsigned long pfn, unsigned nr_pages); | 399 | extern void free_contig_range(unsigned long pfn, unsigned nr_pages); |
| 399 | 400 | ||
| 400 | /* CMA stuff */ | 401 | /* CMA stuff */ |
diff --git a/include/linux/page-isolation.h b/include/linux/page-isolation.h index 051c1b1ede4e..3bdcab30ca41 100644 --- a/include/linux/page-isolation.h +++ b/include/linux/page-isolation.h | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | /* | 4 | /* |
| 5 | * Changes migrate type in [start_pfn, end_pfn) to be MIGRATE_ISOLATE. | 5 | * Changes migrate type in [start_pfn, end_pfn) to be MIGRATE_ISOLATE. |
| 6 | * If specified range includes migrate types other than MOVABLE, | 6 | * If specified range includes migrate types other than MOVABLE or CMA, |
| 7 | * this will fail with -EBUSY. | 7 | * this will fail with -EBUSY. |
| 8 | * | 8 | * |
| 9 | * For isolating all pages in the range finally, the caller have to | 9 | * For isolating all pages in the range finally, the caller have to |
| @@ -11,27 +11,27 @@ | |||
| 11 | * test it. | 11 | * test it. |
| 12 | */ | 12 | */ |
| 13 | extern int | 13 | extern int |
| 14 | start_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn); | 14 | start_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn, |
| 15 | unsigned migratetype); | ||
| 15 | 16 | ||
| 16 | /* | 17 | /* |
| 17 | * Changes MIGRATE_ISOLATE to MIGRATE_MOVABLE. | 18 | * Changes MIGRATE_ISOLATE to MIGRATE_MOVABLE. |
| 18 | * target range is [start_pfn, end_pfn) | 19 | * target range is [start_pfn, end_pfn) |
| 19 | */ | 20 | */ |
| 20 | extern int | 21 | extern int |
| 21 | undo_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn); | 22 | undo_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn, |
| 23 | unsigned migratetype); | ||
| 22 | 24 | ||
| 23 | /* | 25 | /* |
| 24 | * test all pages in [start_pfn, end_pfn)are isolated or not. | 26 | * Test all pages in [start_pfn, end_pfn) are isolated or not. |
| 25 | */ | 27 | */ |
| 26 | extern int | 28 | int test_pages_isolated(unsigned long start_pfn, unsigned long end_pfn); |
| 27 | test_pages_isolated(unsigned long start_pfn, unsigned long end_pfn); | ||
| 28 | 29 | ||
| 29 | /* | 30 | /* |
| 30 | * Internal funcs.Changes pageblock's migrate type. | 31 | * Internal functions. Changes pageblock's migrate type. |
| 31 | * Please use make_pagetype_isolated()/make_pagetype_movable(). | ||
| 32 | */ | 32 | */ |
| 33 | extern int set_migratetype_isolate(struct page *page); | 33 | extern int set_migratetype_isolate(struct page *page); |
| 34 | extern void unset_migratetype_isolate(struct page *page); | 34 | extern void unset_migratetype_isolate(struct page *page, unsigned migratetype); |
| 35 | 35 | ||
| 36 | 36 | ||
| 37 | #endif | 37 | #endif |
diff --git a/mm/memory-failure.c b/mm/memory-failure.c index 97cc2733551a..c99ad4e6b88c 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c | |||
| @@ -1404,7 +1404,7 @@ static int get_any_page(struct page *p, unsigned long pfn, int flags) | |||
| 1404 | /* Not a free page */ | 1404 | /* Not a free page */ |
| 1405 | ret = 1; | 1405 | ret = 1; |
| 1406 | } | 1406 | } |
| 1407 | unset_migratetype_isolate(p); | 1407 | unset_migratetype_isolate(p, MIGRATE_MOVABLE); |
| 1408 | unlock_memory_hotplug(); | 1408 | unlock_memory_hotplug(); |
| 1409 | return ret; | 1409 | return ret; |
| 1410 | } | 1410 | } |
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index 6629fafd6ce4..fc898cb4fe8f 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c | |||
| @@ -891,7 +891,7 @@ static int __ref offline_pages(unsigned long start_pfn, | |||
| 891 | nr_pages = end_pfn - start_pfn; | 891 | nr_pages = end_pfn - start_pfn; |
| 892 | 892 | ||
| 893 | /* set above range as isolated */ | 893 | /* set above range as isolated */ |
| 894 | ret = start_isolate_page_range(start_pfn, end_pfn); | 894 | ret = start_isolate_page_range(start_pfn, end_pfn, MIGRATE_MOVABLE); |
| 895 | if (ret) | 895 | if (ret) |
| 896 | goto out; | 896 | goto out; |
| 897 | 897 | ||
| @@ -956,7 +956,7 @@ repeat: | |||
| 956 | We cannot do rollback at this point. */ | 956 | We cannot do rollback at this point. */ |
| 957 | offline_isolated_pages(start_pfn, end_pfn); | 957 | offline_isolated_pages(start_pfn, end_pfn); |
| 958 | /* reset pagetype flags and makes migrate type to be MOVABLE */ | 958 | /* reset pagetype flags and makes migrate type to be MOVABLE */ |
| 959 | undo_isolate_page_range(start_pfn, end_pfn); | 959 | undo_isolate_page_range(start_pfn, end_pfn, MIGRATE_MOVABLE); |
| 960 | /* removal success */ | 960 | /* removal success */ |
| 961 | zone->present_pages -= offlined_pages; | 961 | zone->present_pages -= offlined_pages; |
| 962 | zone->zone_pgdat->node_present_pages -= offlined_pages; | 962 | zone->zone_pgdat->node_present_pages -= offlined_pages; |
| @@ -981,7 +981,7 @@ failed_removal: | |||
| 981 | start_pfn, end_pfn); | 981 | start_pfn, end_pfn); |
| 982 | memory_notify(MEM_CANCEL_OFFLINE, &arg); | 982 | memory_notify(MEM_CANCEL_OFFLINE, &arg); |
| 983 | /* pushback to free area */ | 983 | /* pushback to free area */ |
| 984 | undo_isolate_page_range(start_pfn, end_pfn); | 984 | undo_isolate_page_range(start_pfn, end_pfn, MIGRATE_MOVABLE); |
| 985 | 985 | ||
| 986 | out: | 986 | out: |
| 987 | unlock_memory_hotplug(); | 987 | unlock_memory_hotplug(); |
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 0869eb1e9461..116c087f76bb 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
| @@ -5582,7 +5582,7 @@ out: | |||
| 5582 | return ret; | 5582 | return ret; |
| 5583 | } | 5583 | } |
| 5584 | 5584 | ||
| 5585 | void unset_migratetype_isolate(struct page *page) | 5585 | void unset_migratetype_isolate(struct page *page, unsigned migratetype) |
| 5586 | { | 5586 | { |
| 5587 | struct zone *zone; | 5587 | struct zone *zone; |
| 5588 | unsigned long flags; | 5588 | unsigned long flags; |
| @@ -5590,8 +5590,8 @@ void unset_migratetype_isolate(struct page *page) | |||
| 5590 | spin_lock_irqsave(&zone->lock, flags); | 5590 | spin_lock_irqsave(&zone->lock, flags); |
| 5591 | if (get_pageblock_migratetype(page) != MIGRATE_ISOLATE) | 5591 | if (get_pageblock_migratetype(page) != MIGRATE_ISOLATE) |
| 5592 | goto out; | 5592 | goto out; |
| 5593 | set_pageblock_migratetype(page, MIGRATE_MOVABLE); | 5593 | set_pageblock_migratetype(page, migratetype); |
| 5594 | move_freepages_block(zone, page, MIGRATE_MOVABLE); | 5594 | move_freepages_block(zone, page, migratetype); |
| 5595 | out: | 5595 | out: |
| 5596 | spin_unlock_irqrestore(&zone->lock, flags); | 5596 | spin_unlock_irqrestore(&zone->lock, flags); |
| 5597 | } | 5597 | } |
| @@ -5669,6 +5669,10 @@ static int __alloc_contig_migrate_range(unsigned long start, unsigned long end) | |||
| 5669 | * alloc_contig_range() -- tries to allocate given range of pages | 5669 | * alloc_contig_range() -- tries to allocate given range of pages |
| 5670 | * @start: start PFN to allocate | 5670 | * @start: start PFN to allocate |
| 5671 | * @end: one-past-the-last PFN to allocate | 5671 | * @end: one-past-the-last PFN to allocate |
| 5672 | * @migratetype: migratetype of the underlaying pageblocks (either | ||
| 5673 | * #MIGRATE_MOVABLE or #MIGRATE_CMA). All pageblocks | ||
| 5674 | * in range must have the same migratetype and it must | ||
| 5675 | * be either of the two. | ||
| 5672 | * | 5676 | * |
| 5673 | * The PFN range does not have to be pageblock or MAX_ORDER_NR_PAGES | 5677 | * The PFN range does not have to be pageblock or MAX_ORDER_NR_PAGES |
| 5674 | * aligned, however it's the caller's responsibility to guarantee that | 5678 | * aligned, however it's the caller's responsibility to guarantee that |
| @@ -5681,7 +5685,8 @@ static int __alloc_contig_migrate_range(unsigned long start, unsigned long end) | |||
| 5681 | * pages which PFN is in [start, end) are allocated for the caller and | 5685 | * pages which PFN is in [start, end) are allocated for the caller and |
| 5682 | * need to be freed with free_contig_range(). | 5686 | * need to be freed with free_contig_range(). |
| 5683 | */ | 5687 | */ |
| 5684 | int alloc_contig_range(unsigned long start, unsigned long end) | 5688 | int alloc_contig_range(unsigned long start, unsigned long end, |
| 5689 | unsigned migratetype) | ||
| 5685 | { | 5690 | { |
| 5686 | struct zone *zone = page_zone(pfn_to_page(start)); | 5691 | struct zone *zone = page_zone(pfn_to_page(start)); |
| 5687 | unsigned long outer_start, outer_end; | 5692 | unsigned long outer_start, outer_end; |
| @@ -5712,7 +5717,7 @@ int alloc_contig_range(unsigned long start, unsigned long end) | |||
| 5712 | */ | 5717 | */ |
| 5713 | 5718 | ||
| 5714 | ret = start_isolate_page_range(pfn_max_align_down(start), | 5719 | ret = start_isolate_page_range(pfn_max_align_down(start), |
| 5715 | pfn_max_align_up(end)); | 5720 | pfn_max_align_up(end), migratetype); |
| 5716 | if (ret) | 5721 | if (ret) |
| 5717 | goto done; | 5722 | goto done; |
| 5718 | 5723 | ||
| @@ -5772,7 +5777,7 @@ int alloc_contig_range(unsigned long start, unsigned long end) | |||
| 5772 | 5777 | ||
| 5773 | done: | 5778 | done: |
| 5774 | undo_isolate_page_range(pfn_max_align_down(start), | 5779 | undo_isolate_page_range(pfn_max_align_down(start), |
| 5775 | pfn_max_align_up(end)); | 5780 | pfn_max_align_up(end), migratetype); |
| 5776 | return ret; | 5781 | return ret; |
| 5777 | } | 5782 | } |
| 5778 | 5783 | ||
diff --git a/mm/page_isolation.c b/mm/page_isolation.c index 4ae42bb40892..c9f04774f2b8 100644 --- a/mm/page_isolation.c +++ b/mm/page_isolation.c | |||
| @@ -24,6 +24,7 @@ __first_valid_page(unsigned long pfn, unsigned long nr_pages) | |||
| 24 | * to be MIGRATE_ISOLATE. | 24 | * to be MIGRATE_ISOLATE. |
| 25 | * @start_pfn: The lower PFN of the range to be isolated. | 25 | * @start_pfn: The lower PFN of the range to be isolated. |
| 26 | * @end_pfn: The upper PFN of the range to be isolated. | 26 | * @end_pfn: The upper PFN of the range to be isolated. |
| 27 | * @migratetype: migrate type to set in error recovery. | ||
| 27 | * | 28 | * |
| 28 | * Making page-allocation-type to be MIGRATE_ISOLATE means free pages in | 29 | * Making page-allocation-type to be MIGRATE_ISOLATE means free pages in |
| 29 | * the range will never be allocated. Any free pages and pages freed in the | 30 | * the range will never be allocated. Any free pages and pages freed in the |
| @@ -32,8 +33,8 @@ __first_valid_page(unsigned long pfn, unsigned long nr_pages) | |||
| 32 | * start_pfn/end_pfn must be aligned to pageblock_order. | 33 | * start_pfn/end_pfn must be aligned to pageblock_order. |
| 33 | * Returns 0 on success and -EBUSY if any part of range cannot be isolated. | 34 | * Returns 0 on success and -EBUSY if any part of range cannot be isolated. |
| 34 | */ | 35 | */ |
| 35 | int | 36 | int start_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn, |
| 36 | start_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn) | 37 | unsigned migratetype) |
| 37 | { | 38 | { |
| 38 | unsigned long pfn; | 39 | unsigned long pfn; |
| 39 | unsigned long undo_pfn; | 40 | unsigned long undo_pfn; |
| @@ -56,7 +57,7 @@ undo: | |||
| 56 | for (pfn = start_pfn; | 57 | for (pfn = start_pfn; |
| 57 | pfn < undo_pfn; | 58 | pfn < undo_pfn; |
| 58 | pfn += pageblock_nr_pages) | 59 | pfn += pageblock_nr_pages) |
| 59 | unset_migratetype_isolate(pfn_to_page(pfn)); | 60 | unset_migratetype_isolate(pfn_to_page(pfn), migratetype); |
| 60 | 61 | ||
| 61 | return -EBUSY; | 62 | return -EBUSY; |
| 62 | } | 63 | } |
| @@ -64,8 +65,8 @@ undo: | |||
| 64 | /* | 65 | /* |
| 65 | * Make isolated pages available again. | 66 | * Make isolated pages available again. |
| 66 | */ | 67 | */ |
| 67 | int | 68 | int undo_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn, |
| 68 | undo_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn) | 69 | unsigned migratetype) |
| 69 | { | 70 | { |
| 70 | unsigned long pfn; | 71 | unsigned long pfn; |
| 71 | struct page *page; | 72 | struct page *page; |
| @@ -77,7 +78,7 @@ undo_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn) | |||
| 77 | page = __first_valid_page(pfn, pageblock_nr_pages); | 78 | page = __first_valid_page(pfn, pageblock_nr_pages); |
| 78 | if (!page || get_pageblock_migratetype(page) != MIGRATE_ISOLATE) | 79 | if (!page || get_pageblock_migratetype(page) != MIGRATE_ISOLATE) |
| 79 | continue; | 80 | continue; |
| 80 | unset_migratetype_isolate(page); | 81 | unset_migratetype_isolate(page, migratetype); |
| 81 | } | 82 | } |
| 82 | return 0; | 83 | return 0; |
| 83 | } | 84 | } |
| @@ -86,7 +87,7 @@ undo_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn) | |||
| 86 | * all pages in [start_pfn...end_pfn) must be in the same zone. | 87 | * all pages in [start_pfn...end_pfn) must be in the same zone. |
| 87 | * zone->lock must be held before call this. | 88 | * zone->lock must be held before call this. |
| 88 | * | 89 | * |
| 89 | * Returns 1 if all pages in the range is isolated. | 90 | * Returns 1 if all pages in the range are isolated. |
| 90 | */ | 91 | */ |
| 91 | static int | 92 | static int |
| 92 | __test_page_isolated_in_pageblock(unsigned long pfn, unsigned long end_pfn) | 93 | __test_page_isolated_in_pageblock(unsigned long pfn, unsigned long end_pfn) |
