aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichal Nazarewicz <mina86@mina86.com>2012-04-03 09:06:15 -0400
committerMarek Szyprowski <m.szyprowski@samsung.com>2012-05-21 09:09:33 -0400
commit0815f3d81d76dfbf2abcfd93a85ff0a6008fe4c0 (patch)
tree750e239c7c522a206bb04bd8bfcd89c3bf3be30d
parent47118af076f64844b4f423bc2f545b2da9dab50d (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.h3
-rw-r--r--include/linux/page-isolation.h18
-rw-r--r--mm/memory-failure.c2
-rw-r--r--mm/memory_hotplug.c6
-rw-r--r--mm/page_alloc.c17
-rw-r--r--mm/page_isolation.c15
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. */
397extern int alloc_contig_range(unsigned long start, unsigned long end); 397extern int alloc_contig_range(unsigned long start, unsigned long end,
398 unsigned migratetype);
398extern void free_contig_range(unsigned long pfn, unsigned nr_pages); 399extern 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 */
13extern int 13extern int
14start_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn); 14start_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 */
20extern int 21extern int
21undo_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn); 22undo_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 */
26extern int 28int test_pages_isolated(unsigned long start_pfn, unsigned long end_pfn);
27test_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 */
33extern int set_migratetype_isolate(struct page *page); 33extern int set_migratetype_isolate(struct page *page);
34extern void unset_migratetype_isolate(struct page *page); 34extern 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
986out: 986out:
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
5585void unset_migratetype_isolate(struct page *page) 5585void 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);
5595out: 5595out:
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 */
5684int alloc_contig_range(unsigned long start, unsigned long end) 5688int 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
5773done: 5778done:
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 */
35int 36int start_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn,
36start_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 */
67int 68int undo_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn,
68undo_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 */
91static int 92static 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)