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

mm/page_isolation: remove migratetype parameter from more functions

migratetype is no longer overwritten during pageblock isolation,
start_isolate_page_range(), has_unmovable_pages(), and
set_migratetype_isolate() no longer need which migratetype to restore
during isolation failure.

For has_unmoable_pages(), it needs to know if the isolation is for CMA
allocation, so adding PB_ISOLATE_MODE_CMA_ALLOC provide the information.
At the same time change isolation flags to enum pb_isolate_mode
(PB_ISOLATE_MODE_MEM_OFFLINE, PB_ISOLATE_MODE_CMA_ALLOC,
PB_ISOLATE_MODE_OTHER). Remove REPORT_FAILURE and check
PB_ISOLATE_MODE_MEM_OFFLINE, since only PB_ISOLATE_MODE_MEM_OFFLINE
reports isolation failures.

alloc_contig_range() no longer needs migratetype. Replace it with a newly
defined acr_flags_t to tell if an allocation is for CMA. So does
__alloc_contig_migrate_range(). Add ACR_FLAGS_NONE (set to 0) to indicate
ordinary allocations.

Link: https://lkml.kernel.org/r/20250617021115.2331563-7-ziy@nvidia.com
Signed-off-by: Zi Yan <ziy@nvidia.com>
Reviewed-by: Vlastimil Babka <vbabka@suse.cz>
Acked-by: David Hildenbrand <david@redhat.com>
Cc: Baolin Wang <baolin.wang@linux.alibaba.com>
Cc: Brendan Jackman <jackmanb@google.com>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Kirill A. Shuemov <kirill.shutemov@linux.intel.com>
Cc: Mel Gorman <mgorman@techsingularity.net>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Oscar Salvador <osalvador@suse.de>
Cc: Richard Chang <richardycc@google.com>
Cc: Suren Baghdasaryan <surenb@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

Zi Yan and committed by
Andrew Morton
d1554fb6 7a3324eb

+80 -68
+1 -1
drivers/virtio/virtio_mem.c
··· 1243 1243 if (atomic_read(&vm->config_changed)) 1244 1244 return -EAGAIN; 1245 1245 1246 - rc = alloc_contig_range(pfn, pfn + nr_pages, MIGRATE_MOVABLE, 1246 + rc = alloc_contig_range(pfn, pfn + nr_pages, ACR_FLAGS_NONE, 1247 1247 GFP_KERNEL); 1248 1248 if (rc == -ENOMEM) 1249 1249 /* whoops, out of memory */
+6 -1
include/linux/gfp.h
··· 423 423 extern gfp_t vma_thp_gfp_mask(struct vm_area_struct *vma); 424 424 425 425 #ifdef CONFIG_CONTIG_ALLOC 426 + 427 + typedef unsigned int __bitwise acr_flags_t; 428 + #define ACR_FLAGS_NONE ((__force acr_flags_t)0) // ordinary allocation request 429 + #define ACR_FLAGS_CMA ((__force acr_flags_t)BIT(0)) // allocate for CMA 430 + 426 431 /* The below functions must be run on a range from a single zone. */ 427 432 extern int alloc_contig_range_noprof(unsigned long start, unsigned long end, 428 - unsigned migratetype, gfp_t gfp_mask); 433 + acr_flags_t alloc_flags, gfp_t gfp_mask); 429 434 #define alloc_contig_range(...) alloc_hooks(alloc_contig_range_noprof(__VA_ARGS__)) 430 435 431 436 extern struct page *alloc_contig_pages_noprof(unsigned long nr_pages, gfp_t gfp_mask,
+16 -4
include/linux/page-isolation.h
··· 38 38 } 39 39 #endif 40 40 41 - #define MEMORY_OFFLINE 0x1 42 - #define REPORT_FAILURE 0x2 41 + /* 42 + * Pageblock isolation modes: 43 + * PB_ISOLATE_MODE_MEM_OFFLINE - isolate to offline (!allocate) memory 44 + * e.g., skip over PageHWPoison() pages and 45 + * PageOffline() pages. Unmovable pages will be 46 + * reported in this mode. 47 + * PB_ISOLATE_MODE_CMA_ALLOC - isolate for CMA allocations 48 + * PB_ISOLATE_MODE_OTHER - isolate for other purposes 49 + */ 50 + enum pb_isolate_mode { 51 + PB_ISOLATE_MODE_MEM_OFFLINE, 52 + PB_ISOLATE_MODE_CMA_ALLOC, 53 + PB_ISOLATE_MODE_OTHER, 54 + }; 43 55 44 56 void __meminit init_pageblock_migratetype(struct page *page, 45 57 enum migratetype migratetype, ··· 61 49 bool pageblock_unisolate_and_move_free_pages(struct zone *zone, struct page *page); 62 50 63 51 int start_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn, 64 - int migratetype, int flags); 52 + enum pb_isolate_mode mode); 65 53 66 54 void undo_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn); 67 55 68 56 int test_pages_isolated(unsigned long start_pfn, unsigned long end_pfn, 69 - int isol_flags); 57 + enum pb_isolate_mode mode); 70 58 #endif
+8 -6
include/trace/events/kmem.h
··· 304 304 __entry->change_ownership) 305 305 ); 306 306 307 + #ifdef CONFIG_CONTIG_ALLOC 307 308 TRACE_EVENT(mm_alloc_contig_migrate_range_info, 308 309 309 310 TP_PROTO(unsigned long start, ··· 312 311 unsigned long nr_migrated, 313 312 unsigned long nr_reclaimed, 314 313 unsigned long nr_mapped, 315 - int migratetype), 314 + acr_flags_t alloc_flags), 316 315 317 - TP_ARGS(start, end, nr_migrated, nr_reclaimed, nr_mapped, migratetype), 316 + TP_ARGS(start, end, nr_migrated, nr_reclaimed, nr_mapped, alloc_flags), 318 317 319 318 TP_STRUCT__entry( 320 319 __field(unsigned long, start) ··· 322 321 __field(unsigned long, nr_migrated) 323 322 __field(unsigned long, nr_reclaimed) 324 323 __field(unsigned long, nr_mapped) 325 - __field(int, migratetype) 324 + __field(acr_flags_t, alloc_flags) 326 325 ), 327 326 328 327 TP_fast_assign( ··· 331 330 __entry->nr_migrated = nr_migrated; 332 331 __entry->nr_reclaimed = nr_reclaimed; 333 332 __entry->nr_mapped = nr_mapped; 334 - __entry->migratetype = migratetype; 333 + __entry->alloc_flags = alloc_flags; 335 334 ), 336 335 337 - TP_printk("start=0x%lx end=0x%lx migratetype=%d nr_migrated=%lu nr_reclaimed=%lu nr_mapped=%lu", 336 + TP_printk("start=0x%lx end=0x%lx alloc_flags=%d nr_migrated=%lu nr_reclaimed=%lu nr_mapped=%lu", 338 337 __entry->start, 339 338 __entry->end, 340 - __entry->migratetype, 339 + __entry->alloc_flags, 341 340 __entry->nr_migrated, 342 341 __entry->nr_reclaimed, 343 342 __entry->nr_mapped) 344 343 ); 344 + #endif 345 345 346 346 TRACE_EVENT(mm_setup_per_zone_wmarks, 347 347
+1 -1
mm/cma.c
··· 822 822 823 823 pfn = cmr->base_pfn + (bitmap_no << cma->order_per_bit); 824 824 mutex_lock(&cma->alloc_mutex); 825 - ret = alloc_contig_range(pfn, pfn + count, MIGRATE_CMA, gfp); 825 + ret = alloc_contig_range(pfn, pfn + count, ACR_FLAGS_CMA, gfp); 826 826 mutex_unlock(&cma->alloc_mutex); 827 827 if (ret == 0) { 828 828 page = pfn_to_page(pfn);
+3 -3
mm/memory_hotplug.c
··· 1962 1962 1963 1963 /* set above range as isolated */ 1964 1964 ret = start_isolate_page_range(start_pfn, end_pfn, 1965 - MIGRATE_MOVABLE, 1966 - MEMORY_OFFLINE | REPORT_FAILURE); 1965 + PB_ISOLATE_MODE_MEM_OFFLINE); 1967 1966 if (ret) { 1968 1967 reason = "failure to isolate range"; 1969 1968 goto failed_removal_pcplists_disabled; ··· 2032 2033 goto failed_removal_isolated; 2033 2034 } 2034 2035 2035 - ret = test_pages_isolated(start_pfn, end_pfn, MEMORY_OFFLINE); 2036 + ret = test_pages_isolated(start_pfn, end_pfn, 2037 + PB_ISOLATE_MODE_MEM_OFFLINE); 2036 2038 2037 2039 } while (ret); 2038 2040
+14 -13
mm/page_alloc.c
··· 6693 6693 6694 6694 /* 6695 6695 * [start, end) must belong to a single zone. 6696 - * @migratetype: using migratetype to filter the type of migration in 6696 + * @alloc_flags: using acr_flags_t to filter the type of migration in 6697 6697 * trace_mm_alloc_contig_migrate_range_info. 6698 6698 */ 6699 6699 static int __alloc_contig_migrate_range(struct compact_control *cc, 6700 - unsigned long start, unsigned long end, int migratetype) 6700 + unsigned long start, unsigned long end, 6701 + acr_flags_t alloc_flags) 6701 6702 { 6702 6703 /* This function is based on compact_zone() from compaction.c. */ 6703 6704 unsigned int nr_reclaimed; ··· 6770 6769 putback_movable_pages(&cc->migratepages); 6771 6770 } 6772 6771 6773 - trace_mm_alloc_contig_migrate_range_info(start, end, migratetype, 6772 + trace_mm_alloc_contig_migrate_range_info(start, end, alloc_flags, 6774 6773 total_migrated, 6775 6774 total_reclaimed, 6776 6775 total_mapped); ··· 6841 6840 * alloc_contig_range() -- tries to allocate given range of pages 6842 6841 * @start: start PFN to allocate 6843 6842 * @end: one-past-the-last PFN to allocate 6844 - * @migratetype: migratetype of the underlying pageblocks (either 6845 - * #MIGRATE_MOVABLE or #MIGRATE_CMA). All pageblocks 6846 - * in range must have the same migratetype and it must 6847 - * be either of the two. 6843 + * @alloc_flags: allocation information 6848 6844 * @gfp_mask: GFP mask. Node/zone/placement hints are ignored; only some 6849 6845 * action and reclaim modifiers are supported. Reclaim modifiers 6850 6846 * control allocation behavior during compaction/migration/reclaim. ··· 6858 6860 * need to be freed with free_contig_range(). 6859 6861 */ 6860 6862 int alloc_contig_range_noprof(unsigned long start, unsigned long end, 6861 - unsigned migratetype, gfp_t gfp_mask) 6863 + acr_flags_t alloc_flags, gfp_t gfp_mask) 6862 6864 { 6863 6865 unsigned long outer_start, outer_end; 6864 6866 int ret = 0; ··· 6873 6875 .alloc_contig = true, 6874 6876 }; 6875 6877 INIT_LIST_HEAD(&cc.migratepages); 6878 + enum pb_isolate_mode mode = (alloc_flags & ACR_FLAGS_CMA) ? 6879 + PB_ISOLATE_MODE_CMA_ALLOC : 6880 + PB_ISOLATE_MODE_OTHER; 6876 6881 6877 6882 gfp_mask = current_gfp_context(gfp_mask); 6878 6883 if (__alloc_contig_verify_gfp_mask(gfp_mask, (gfp_t *)&cc.gfp_mask)) ··· 6902 6901 * put back to page allocator so that buddy can use them. 6903 6902 */ 6904 6903 6905 - ret = start_isolate_page_range(start, end, migratetype, 0); 6904 + ret = start_isolate_page_range(start, end, mode); 6906 6905 if (ret) 6907 6906 goto done; 6908 6907 ··· 6918 6917 * allocated. So, if we fall through be sure to clear ret so that 6919 6918 * -EBUSY is not accidentally used or returned to caller. 6920 6919 */ 6921 - ret = __alloc_contig_migrate_range(&cc, start, end, migratetype); 6920 + ret = __alloc_contig_migrate_range(&cc, start, end, alloc_flags); 6922 6921 if (ret && ret != -EBUSY) 6923 6922 goto done; 6924 6923 ··· 6952 6951 outer_start = find_large_buddy(start); 6953 6952 6954 6953 /* Make sure the range is really isolated. */ 6955 - if (test_pages_isolated(outer_start, end, 0)) { 6954 + if (test_pages_isolated(outer_start, end, mode)) { 6956 6955 ret = -EBUSY; 6957 6956 goto done; 6958 6957 } ··· 6995 6994 { 6996 6995 unsigned long end_pfn = start_pfn + nr_pages; 6997 6996 6998 - return alloc_contig_range_noprof(start_pfn, end_pfn, MIGRATE_MOVABLE, 6999 - gfp_mask); 6997 + return alloc_contig_range_noprof(start_pfn, end_pfn, ACR_FLAGS_NONE, 6998 + gfp_mask); 7000 6999 } 7001 7000 7002 7001 static bool pfn_range_valid_contig(struct zone *z, unsigned long start_pfn,
+31 -39
mm/page_isolation.c
··· 31 31 * 32 32 */ 33 33 static struct page *has_unmovable_pages(unsigned long start_pfn, unsigned long end_pfn, 34 - int migratetype, int flags) 34 + enum pb_isolate_mode mode) 35 35 { 36 36 struct page *page = pfn_to_page(start_pfn); 37 37 struct zone *zone = page_zone(page); ··· 46 46 * isolate CMA pageblocks even when they are not movable in fact 47 47 * so consider them movable here. 48 48 */ 49 - if (is_migrate_cma(migratetype)) 49 + if (mode == PB_ISOLATE_MODE_CMA_ALLOC) 50 50 return NULL; 51 51 52 52 return page; ··· 117 117 * The HWPoisoned page may be not in buddy system, and 118 118 * page_count() is not 0. 119 119 */ 120 - if ((flags & MEMORY_OFFLINE) && PageHWPoison(page)) 120 + if ((mode == PB_ISOLATE_MODE_MEM_OFFLINE) && PageHWPoison(page)) 121 121 continue; 122 122 123 123 /* ··· 130 130 * move these pages that still have a reference count > 0. 131 131 * (false negatives in this function only) 132 132 */ 133 - if ((flags & MEMORY_OFFLINE) && PageOffline(page)) 133 + if ((mode == PB_ISOLATE_MODE_MEM_OFFLINE) && PageOffline(page)) 134 134 continue; 135 135 136 136 if (__PageMovable(page) || PageLRU(page)) ··· 151 151 * present in [start_pfn, end_pfn). The pageblock must intersect with 152 152 * [start_pfn, end_pfn). 153 153 */ 154 - static int set_migratetype_isolate(struct page *page, int migratetype, int isol_flags, 154 + static int set_migratetype_isolate(struct page *page, enum pb_isolate_mode mode, 155 155 unsigned long start_pfn, unsigned long end_pfn) 156 156 { 157 157 struct zone *zone = page_zone(page); ··· 186 186 end_pfn); 187 187 188 188 unmovable = has_unmovable_pages(check_unmovable_start, check_unmovable_end, 189 - migratetype, isol_flags); 189 + mode); 190 190 if (!unmovable) { 191 191 if (!pageblock_isolate_and_move_free_pages(zone, page)) { 192 192 spin_unlock_irqrestore(&zone->lock, flags); ··· 198 198 } 199 199 200 200 spin_unlock_irqrestore(&zone->lock, flags); 201 - if (isol_flags & REPORT_FAILURE) { 201 + if (mode == PB_ISOLATE_MODE_MEM_OFFLINE) { 202 202 /* 203 203 * printk() with zone->lock held will likely trigger a 204 204 * lockdep splat, so defer it here. ··· 292 292 * isolate_single_pageblock() -- tries to isolate a pageblock that might be 293 293 * within a free or in-use page. 294 294 * @boundary_pfn: pageblock-aligned pfn that a page might cross 295 - * @flags: isolation flags 295 + * @mode: isolation mode 296 296 * @isolate_before: isolate the pageblock before the boundary_pfn 297 297 * @skip_isolation: the flag to skip the pageblock isolation in second 298 298 * isolate_single_pageblock() 299 - * @migratetype: migrate type to set in error recovery. 300 299 * 301 300 * Free and in-use pages can be as big as MAX_PAGE_ORDER and contain more than one 302 301 * pageblock. When not all pageblocks within a page are isolated at the same ··· 310 311 * either. The function handles this by splitting the free page or migrating 311 312 * the in-use page then splitting the free page. 312 313 */ 313 - static int isolate_single_pageblock(unsigned long boundary_pfn, int flags, 314 - bool isolate_before, bool skip_isolation, int migratetype) 314 + static int isolate_single_pageblock(unsigned long boundary_pfn, 315 + enum pb_isolate_mode mode, bool isolate_before, 316 + bool skip_isolation) 315 317 { 316 318 unsigned long start_pfn; 317 319 unsigned long isolate_pageblock; ··· 338 338 zone->zone_start_pfn); 339 339 340 340 if (skip_isolation) { 341 - int mt __maybe_unused = get_pageblock_migratetype(pfn_to_page(isolate_pageblock)); 342 - 343 - VM_BUG_ON(!is_migrate_isolate(mt)); 341 + VM_BUG_ON(!get_pageblock_isolate(pfn_to_page(isolate_pageblock))); 344 342 } else { 345 - ret = set_migratetype_isolate(pfn_to_page(isolate_pageblock), migratetype, 346 - flags, isolate_pageblock, isolate_pageblock + pageblock_nr_pages); 343 + ret = set_migratetype_isolate(pfn_to_page(isolate_pageblock), 344 + mode, isolate_pageblock, 345 + isolate_pageblock + pageblock_nr_pages); 347 346 348 347 if (ret) 349 348 return ret; ··· 440 441 * start_isolate_page_range() - mark page range MIGRATE_ISOLATE 441 442 * @start_pfn: The first PFN of the range to be isolated. 442 443 * @end_pfn: The last PFN of the range to be isolated. 443 - * @migratetype: Migrate type to set in error recovery. 444 - * @flags: The following flags are allowed (they can be combined in 445 - * a bit mask) 446 - * MEMORY_OFFLINE - isolate to offline (!allocate) memory 447 - * e.g., skip over PageHWPoison() pages 448 - * and PageOffline() pages. 449 - * REPORT_FAILURE - report details about the failure to 450 - * isolate the range 444 + * @mode: isolation mode 451 445 * 452 446 * Making page-allocation-type to be MIGRATE_ISOLATE means free pages in 453 447 * the range will never be allocated. Any free pages and pages freed in the ··· 473 481 * Return: 0 on success and -EBUSY if any part of range cannot be isolated. 474 482 */ 475 483 int start_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn, 476 - int migratetype, int flags) 484 + enum pb_isolate_mode mode) 477 485 { 478 486 unsigned long pfn; 479 487 struct page *page; ··· 484 492 bool skip_isolation = false; 485 493 486 494 /* isolate [isolate_start, isolate_start + pageblock_nr_pages) pageblock */ 487 - ret = isolate_single_pageblock(isolate_start, flags, false, 488 - skip_isolation, migratetype); 495 + ret = isolate_single_pageblock(isolate_start, mode, false, 496 + skip_isolation); 489 497 if (ret) 490 498 return ret; 491 499 ··· 493 501 skip_isolation = true; 494 502 495 503 /* isolate [isolate_end - pageblock_nr_pages, isolate_end) pageblock */ 496 - ret = isolate_single_pageblock(isolate_end, flags, true, 497 - skip_isolation, migratetype); 504 + ret = isolate_single_pageblock(isolate_end, mode, true, skip_isolation); 498 505 if (ret) { 499 506 unset_migratetype_isolate(pfn_to_page(isolate_start)); 500 507 return ret; ··· 504 513 pfn < isolate_end - pageblock_nr_pages; 505 514 pfn += pageblock_nr_pages) { 506 515 page = __first_valid_page(pfn, pageblock_nr_pages); 507 - if (page && set_migratetype_isolate(page, migratetype, flags, 508 - start_pfn, end_pfn)) { 516 + if (page && set_migratetype_isolate(page, mode, start_pfn, 517 + end_pfn)) { 509 518 undo_isolate_page_range(isolate_start, pfn); 510 519 unset_migratetype_isolate( 511 520 pfn_to_page(isolate_end - pageblock_nr_pages)); ··· 547 556 */ 548 557 static unsigned long 549 558 __test_page_isolated_in_pageblock(unsigned long pfn, unsigned long end_pfn, 550 - int flags) 559 + enum pb_isolate_mode mode) 551 560 { 552 561 struct page *page; 553 562 ··· 560 569 * simple way to verify that as VM_BUG_ON(), though. 561 570 */ 562 571 pfn += 1 << buddy_order(page); 563 - else if ((flags & MEMORY_OFFLINE) && PageHWPoison(page)) 572 + else if ((mode == PB_ISOLATE_MODE_MEM_OFFLINE) && 573 + PageHWPoison(page)) 564 574 /* A HWPoisoned page cannot be also PageBuddy */ 565 575 pfn++; 566 - else if ((flags & MEMORY_OFFLINE) && PageOffline(page) && 567 - !page_count(page)) 576 + else if ((mode == PB_ISOLATE_MODE_MEM_OFFLINE) && 577 + PageOffline(page) && !page_count(page)) 568 578 /* 569 579 * The responsible driver agreed to skip PageOffline() 570 580 * pages when offlining memory by dropping its ··· 583 591 * test_pages_isolated - check if pageblocks in range are isolated 584 592 * @start_pfn: The first PFN of the isolated range 585 593 * @end_pfn: The first PFN *after* the isolated range 586 - * @isol_flags: Testing mode flags 594 + * @mode: Testing mode 587 595 * 588 596 * This tests if all in the specified range are free. 589 597 * 590 - * If %MEMORY_OFFLINE is specified in @flags, it will consider 598 + * If %PB_ISOLATE_MODE_MEM_OFFLINE specified in @mode, it will consider 591 599 * poisoned and offlined pages free as well. 592 600 * 593 601 * Caller must ensure the requested range doesn't span zones. ··· 595 603 * Returns 0 if true, -EBUSY if one or more pages are in use. 596 604 */ 597 605 int test_pages_isolated(unsigned long start_pfn, unsigned long end_pfn, 598 - int isol_flags) 606 + enum pb_isolate_mode mode) 599 607 { 600 608 unsigned long pfn, flags; 601 609 struct page *page; ··· 631 639 /* Check all pages are free or marked as ISOLATED */ 632 640 zone = page_zone(page); 633 641 spin_lock_irqsave(&zone->lock, flags); 634 - pfn = __test_page_isolated_in_pageblock(start_pfn, end_pfn, isol_flags); 642 + pfn = __test_page_isolated_in_pageblock(start_pfn, end_pfn, mode); 635 643 spin_unlock_irqrestore(&zone->lock, flags); 636 644 637 645 ret = pfn < end_pfn ? -EBUSY : 0;