Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Michal Nazarewicz and committed by
Marek Szyprowski
0815f3d8 47118af0

+34 -27
+2 -1
include/linux/gfp.h
··· 394 394 #ifdef CONFIG_CMA 395 395 396 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 399 extern void free_contig_range(unsigned long pfn, unsigned nr_pages); 399 400 400 401 /* CMA stuff */
+9 -9
include/linux/page-isolation.h
··· 3 3 4 4 /* 5 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 7 * this will fail with -EBUSY. 8 8 * 9 9 * For isolating all pages in the range finally, the caller have to ··· 11 11 * test it. 12 12 */ 13 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 18 * Changes MIGRATE_ISOLATE to MIGRATE_MOVABLE. 18 19 * target range is [start_pfn, end_pfn) 19 20 */ 20 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 27 - test_pages_isolated(unsigned long start_pfn, unsigned long end_pfn); 28 + int test_pages_isolated(unsigned long start_pfn, unsigned long end_pfn); 28 29 29 30 /* 30 - * Internal funcs.Changes pageblock's migrate type. 31 - * Please use make_pagetype_isolated()/make_pagetype_movable(). 31 + * Internal functions. Changes pageblock's migrate type. 32 32 */ 33 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 37 #endif
+1 -1
mm/memory-failure.c
··· 1404 1404 /* Not a free page */ 1405 1405 ret = 1; 1406 1406 } 1407 - unset_migratetype_isolate(p); 1407 + unset_migratetype_isolate(p, MIGRATE_MOVABLE); 1408 1408 unlock_memory_hotplug(); 1409 1409 return ret; 1410 1410 }
+3 -3
mm/memory_hotplug.c
··· 891 891 nr_pages = end_pfn - start_pfn; 892 892 893 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 895 if (ret) 896 896 goto out; 897 897 ··· 956 956 We cannot do rollback at this point. */ 957 957 offline_isolated_pages(start_pfn, end_pfn); 958 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 960 /* removal success */ 961 961 zone->present_pages -= offlined_pages; 962 962 zone->zone_pgdat->node_present_pages -= offlined_pages; ··· 981 981 start_pfn, end_pfn); 982 982 memory_notify(MEM_CANCEL_OFFLINE, &arg); 983 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 986 out: 987 987 unlock_memory_hotplug();
+11 -6
mm/page_alloc.c
··· 5582 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 5587 struct zone *zone; 5588 5588 unsigned long flags; ··· 5590 5590 spin_lock_irqsave(&zone->lock, flags); 5591 5591 if (get_pageblock_migratetype(page) != MIGRATE_ISOLATE) 5592 5592 goto out; 5593 - set_pageblock_migratetype(page, MIGRATE_MOVABLE); 5594 - move_freepages_block(zone, page, MIGRATE_MOVABLE); 5593 + set_pageblock_migratetype(page, migratetype); 5594 + move_freepages_block(zone, page, migratetype); 5595 5595 out: 5596 5596 spin_unlock_irqrestore(&zone->lock, flags); 5597 5597 } ··· 5669 5669 * alloc_contig_range() -- tries to allocate given range of pages 5670 5670 * @start: start PFN to allocate 5671 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 5677 * The PFN range does not have to be pageblock or MAX_ORDER_NR_PAGES 5674 5678 * aligned, however it's the caller's responsibility to guarantee that ··· 5685 5681 * pages which PFN is in [start, end) are allocated for the caller and 5686 5682 * need to be freed with free_contig_range(). 5687 5683 */ 5688 - int alloc_contig_range(unsigned long start, unsigned long end) 5684 + int alloc_contig_range(unsigned long start, unsigned long end, 5685 + unsigned migratetype) 5689 5686 { 5690 5687 struct zone *zone = page_zone(pfn_to_page(start)); 5691 5688 unsigned long outer_start, outer_end; ··· 5717 5712 */ 5718 5713 5719 5714 ret = start_isolate_page_range(pfn_max_align_down(start), 5720 - pfn_max_align_up(end)); 5715 + pfn_max_align_up(end), migratetype); 5721 5716 if (ret) 5722 5717 goto done; 5723 5718 ··· 5777 5772 5778 5773 done: 5779 5774 undo_isolate_page_range(pfn_max_align_down(start), 5780 - pfn_max_align_up(end)); 5775 + pfn_max_align_up(end), migratetype); 5781 5776 return ret; 5782 5777 } 5783 5778
+8 -7
mm/page_isolation.c
··· 24 24 * to be MIGRATE_ISOLATE. 25 25 * @start_pfn: The lower PFN of the range to be isolated. 26 26 * @end_pfn: The upper PFN of the range to be isolated. 27 + * @migratetype: migrate type to set in error recovery. 27 28 * 28 29 * Making page-allocation-type to be MIGRATE_ISOLATE means free pages in 29 30 * the range will never be allocated. Any free pages and pages freed in the ··· 33 32 * start_pfn/end_pfn must be aligned to pageblock_order. 34 33 * Returns 0 on success and -EBUSY if any part of range cannot be isolated. 35 34 */ 36 - int 37 - start_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn) 35 + int start_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn, 36 + unsigned migratetype) 38 37 { 39 38 unsigned long pfn; 40 39 unsigned long undo_pfn; ··· 57 56 for (pfn = start_pfn; 58 57 pfn < undo_pfn; 59 58 pfn += pageblock_nr_pages) 60 - unset_migratetype_isolate(pfn_to_page(pfn)); 59 + unset_migratetype_isolate(pfn_to_page(pfn), migratetype); 61 60 62 61 return -EBUSY; 63 62 } ··· 65 64 /* 66 65 * Make isolated pages available again. 67 66 */ 68 - int 69 - undo_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn) 67 + int undo_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn, 68 + unsigned migratetype) 70 69 { 71 70 unsigned long pfn; 72 71 struct page *page; ··· 78 77 page = __first_valid_page(pfn, pageblock_nr_pages); 79 78 if (!page || get_pageblock_migratetype(page) != MIGRATE_ISOLATE) 80 79 continue; 81 - unset_migratetype_isolate(page); 80 + unset_migratetype_isolate(page, migratetype); 82 81 } 83 82 return 0; 84 83 } ··· 87 86 * all pages in [start_pfn...end_pfn) must be in the same zone. 88 87 * zone->lock must be held before call this. 89 88 * 90 - * Returns 1 if all pages in the range is isolated. 89 + * Returns 1 if all pages in the range are isolated. 91 90 */ 92 91 static int 93 92 __test_page_isolated_in_pageblock(unsigned long pfn, unsigned long end_pfn)