mm: page_isolation: enable arbitrary range page isolation.
authorZi Yan <ziy@nvidia.com>
Fri, 13 May 2022 03:22:58 +0000 (20:22 -0700)
committerAndrew Morton <akpm@linux-foundation.org>
Fri, 13 May 2022 14:20:13 +0000 (07:20 -0700)
Now start_isolate_page_range() is ready to handle arbitrary range
isolation, so move the alignment check/adjustment into the function body.
Do the same for its counterpart undo_isolate_page_range().
alloc_contig_range(), its caller, can pass an arbitrary range instead of a
MAX_ORDER_NR_PAGES aligned one.

Link: https://lkml.kernel.org/r/20220425143118.2850746-5-zi.yan@sent.com
Signed-off-by: Zi Yan <ziy@nvidia.com>
Cc: Christophe Leroy <christophe.leroy@csgroup.eu>
Cc: David Hildenbrand <david@redhat.com>
Cc: Eric Ren <renzhengeek@gmail.com>
Cc: kernel test robot <lkp@intel.com>
Cc: Mel Gorman <mgorman@techsingularity.net>
Cc: Mike Rapoport <rppt@linux.ibm.com>
Cc: Minchan Kim <minchan@kernel.org>
Cc: Oscar Salvador <osalvador@suse.de>
Cc: Vlastimil Babka <vbabka@suse.cz>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
mm/page_alloc.c
mm/page_isolation.c

index 0c7252e..3d7de8a 100644 (file)
@@ -8956,16 +8956,6 @@ void *__init alloc_large_system_hash(const char *tablename,
 }
 
 #ifdef CONFIG_CONTIG_ALLOC
-static unsigned long pfn_max_align_down(unsigned long pfn)
-{
-       return ALIGN_DOWN(pfn, MAX_ORDER_NR_PAGES);
-}
-
-static unsigned long pfn_max_align_up(unsigned long pfn)
-{
-       return ALIGN(pfn, MAX_ORDER_NR_PAGES);
-}
-
 #if defined(CONFIG_DYNAMIC_DEBUG) || \
        (defined(CONFIG_DYNAMIC_DEBUG_CORE) && defined(DYNAMIC_DEBUG_MODULE))
 /* Usage: See admin-guide/dynamic-debug-howto.rst */
@@ -9107,8 +9097,7 @@ int alloc_contig_range(unsigned long start, unsigned long end,
         * put back to page allocator so that buddy can use them.
         */
 
-       ret = start_isolate_page_range(pfn_max_align_down(start),
-                               pfn_max_align_up(end), migratetype, 0, gfp_mask);
+       ret = start_isolate_page_range(start, end, migratetype, 0, gfp_mask);
        if (ret)
                goto done;
 
@@ -9189,8 +9178,7 @@ int alloc_contig_range(unsigned long start, unsigned long end,
                free_contig_range(end, outer_end - end);
 
 done:
-       undo_isolate_page_range(pfn_max_align_down(start),
-                               pfn_max_align_up(end), migratetype);
+       undo_isolate_page_range(start, end, migratetype);
        return ret;
 }
 EXPORT_SYMBOL(alloc_contig_range);
index 8a0f16d..b3f074d 100644 (file)
@@ -444,7 +444,6 @@ failed:
  * be MIGRATE_ISOLATE.
  * @start_pfn:         The lower PFN of the range to be isolated.
  * @end_pfn:           The upper PFN of the range to be isolated.
- *                     start_pfn/end_pfn must be aligned to pageblock_order.
  * @migratetype:       Migrate type to set in error recovery.
  * @flags:             The following flags are allowed (they can be combined in
  *                     a bit mask)
@@ -491,33 +490,33 @@ int start_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn,
 {
        unsigned long pfn;
        struct page *page;
+       /* isolation is done at page block granularity */
+       unsigned long isolate_start = ALIGN_DOWN(start_pfn, pageblock_nr_pages);
+       unsigned long isolate_end = ALIGN(end_pfn, pageblock_nr_pages);
        int ret;
 
-       BUG_ON(!IS_ALIGNED(start_pfn, pageblock_nr_pages));
-       BUG_ON(!IS_ALIGNED(end_pfn, pageblock_nr_pages));
-
-       /* isolate [start_pfn, start_pfn + pageblock_nr_pages) pageblock */
-       ret = isolate_single_pageblock(start_pfn, gfp_flags, false);
+       /* isolate [isolate_start, isolate_start + pageblock_nr_pages) pageblock */
+       ret = isolate_single_pageblock(isolate_start, gfp_flags, false);
        if (ret)
                return ret;
 
-       /* isolate [end_pfn - pageblock_nr_pages, end_pfn) pageblock */
-       ret = isolate_single_pageblock(end_pfn, gfp_flags, true);
+       /* isolate [isolate_end - pageblock_nr_pages, isolate_end) pageblock */
+       ret = isolate_single_pageblock(isolate_end, gfp_flags, true);
        if (ret) {
-               unset_migratetype_isolate(pfn_to_page(start_pfn), migratetype);
+               unset_migratetype_isolate(pfn_to_page(isolate_start), migratetype);
                return ret;
        }
 
        /* skip isolated pageblocks at the beginning and end */
-       for (pfn = start_pfn + pageblock_nr_pages;
-            pfn < end_pfn - pageblock_nr_pages;
+       for (pfn = isolate_start + pageblock_nr_pages;
+            pfn < isolate_end - pageblock_nr_pages;
             pfn += pageblock_nr_pages) {
                page = __first_valid_page(pfn, pageblock_nr_pages);
                if (page && set_migratetype_isolate(page, migratetype, flags,
                                        start_pfn, end_pfn)) {
-                       undo_isolate_page_range(start_pfn, pfn, migratetype);
+                       undo_isolate_page_range(isolate_start, pfn, migratetype);
                        unset_migratetype_isolate(
-                               pfn_to_page(end_pfn - pageblock_nr_pages),
+                               pfn_to_page(isolate_end - pageblock_nr_pages),
                                migratetype);
                        return -EBUSY;
                }
@@ -533,12 +532,12 @@ void undo_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn,
 {
        unsigned long pfn;
        struct page *page;
+       unsigned long isolate_start = ALIGN_DOWN(start_pfn, pageblock_nr_pages);
+       unsigned long isolate_end = ALIGN(end_pfn, pageblock_nr_pages);
 
-       BUG_ON(!IS_ALIGNED(start_pfn, pageblock_nr_pages));
-       BUG_ON(!IS_ALIGNED(end_pfn, pageblock_nr_pages));
 
-       for (pfn = start_pfn;
-            pfn < end_pfn;
+       for (pfn = isolate_start;
+            pfn < isolate_end;
             pfn += pageblock_nr_pages) {
                page = __first_valid_page(pfn, pageblock_nr_pages);
                if (!page || !is_migrate_isolate_page(page))