diff options
author | Michal Nazarewicz <mina86@mina86.com> | 2012-04-03 09:06:15 -0400 |
---|---|---|
committer | Marek Szyprowski <m.szyprowski@samsung.com> | 2012-05-21 09:09:33 -0400 |
commit | 0815f3d81d76dfbf2abcfd93a85ff0a6008fe4c0 (patch) | |
tree | 750e239c7c522a206bb04bd8bfcd89c3bf3be30d | |
parent | 47118af076f64844b4f423bc2f545b2da9dab50d (diff) |
mm: page_isolation: MIGRATE_CMA isolation functions added
This commit changes various functions that change pages and
pageblocks migrate type between MIGRATE_ISOLATE and
MIGRATE_MOVABLE in such a way as to allow to work with
MIGRATE_CMA migrate type.
Signed-off-by: Michal Nazarewicz <mina86@mina86.com>
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Reviewed-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Tested-by: Rob Clark <rob.clark@linaro.org>
Tested-by: Ohad Ben-Cohen <ohad@wizery.com>
Tested-by: Benjamin Gaignard <benjamin.gaignard@linaro.org>
Tested-by: Robert Nelson <robertcnelson@gmail.com>
Tested-by: Barry Song <Baohua.Song@csr.com>
-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) |