OSDN Git Service

mm: Clear page->private when splitting or migrating a page
authorMatthew Wilcox (Oracle) <willy@infradead.org>
Sun, 19 Jun 2022 14:37:32 +0000 (10:37 -0400)
committerMatthew Wilcox (Oracle) <willy@infradead.org>
Thu, 23 Jun 2022 16:21:44 +0000 (12:21 -0400)
In our efforts to remove uses of PG_private, we have found folios with
the private flag clear and folio->private not-NULL.  That is the root
cause behind 642d51fb0775 ("ceph: check folio PG_private bit instead
of folio->private").  It can also affect a few other filesystems that
haven't yet reported a problem.

compaction_alloc() can return a page with uninitialised page->private,
and rather than checking all the callers of migrate_pages(), just zero
page->private after calling get_new_page().  Similarly, the tail pages
from split_huge_page() may also have an uninitialised page->private.

Reported-by: Xiubo Li <xiubli@redhat.com>
Tested-by: Xiubo Li <xiubli@redhat.com>
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
mm/huge_memory.c
mm/migrate.c

index f724800..834f288 100644 (file)
@@ -2377,6 +2377,7 @@ static void __split_huge_page_tail(struct page *head, int tail,
                        page_tail);
        page_tail->mapping = head->mapping;
        page_tail->index = head->index + tail;
+       page_tail->private = 0;
 
        /* Page flags must be visible before we make the page non-compound. */
        smp_wmb();
index e51588e..6c1ea61 100644 (file)
@@ -1106,6 +1106,7 @@ static int unmap_and_move(new_page_t get_new_page,
        if (!newpage)
                return -ENOMEM;
 
+       newpage->private = 0;
        rc = __unmap_and_move(page, newpage, force, mode);
        if (rc == MIGRATEPAGE_SUCCESS)
                set_page_owner_migrate_reason(newpage, reason);