mm/page_isolation: guard against possible putback unisolated page
authorMiaohe Lin <linmiaohe@huawei.com>
Fri, 5 Nov 2021 20:42:19 +0000 (13:42 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 6 Nov 2021 20:30:40 +0000 (13:30 -0700)
Isolating a free page in an isolated pageblock is expected to always
work as watermarks don't apply here.

But if __isolate_free_page() failed, due to condition changes, the page
will be left on the free list.  And the page will be put back to free
list again via __putback_isolated_page().  This may trigger
VM_BUG_ON_PAGE() on page->flags checking in __free_one_page() if
PageReported is set.  Or we will corrupt the free list because
list_add() will be called for pages already on another list.

Add a VM_WARN_ON() to complain about this change.

Link: https://lkml.kernel.org/r/20210914114508.23725-1-linmiaohe@huawei.com
Fixes: 3c605096d315 ("mm/page_alloc: restrict max order of merging on isolated pageblock")
Signed-off-by: Miaohe Lin <linmiaohe@huawei.com>
Reviewed-by: David Hildenbrand <david@redhat.com>
Acked-by: Vlastimil Babka <vbabka@suse.cz>
Cc: John Hubbard <jhubbard@nvidia.com>
Cc: Joonsoo Kim <iamjoonsoo.kim@lge.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
mm/page_isolation.c

index f93cc63..f67c4c7 100644 (file)
@@ -94,8 +94,13 @@ static void unset_migratetype_isolate(struct page *page, unsigned migratetype)
                        buddy = page + (buddy_pfn - pfn);
 
                        if (!is_migrate_isolate_page(buddy)) {
-                               __isolate_free_page(page, order);
-                               isolated_page = true;
+                               isolated_page = !!__isolate_free_page(page, order);
+                               /*
+                                * Isolating a free page in an isolated pageblock
+                                * is expected to always work as watermarks don't
+                                * apply here.
+                                */
+                               VM_WARN_ON(!isolated_page);
                        }
                }
        }