mm/migrate: Add folio_migrate_mapping()
authorMatthew Wilcox (Oracle) <willy@infradead.org>
Fri, 7 May 2021 11:28:40 +0000 (07:28 -0400)
committerMatthew Wilcox (Oracle) <willy@infradead.org>
Mon, 18 Oct 2021 11:49:39 +0000 (07:49 -0400)
Reimplement migrate_page_move_mapping() as a wrapper around
folio_migrate_mapping().  Saves 193 bytes of kernel text.

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: David Howells <dhowells@redhat.com>
Acked-by: Vlastimil Babka <vbabka@suse.cz>
include/linux/migrate.h
mm/folio-compat.c
mm/migrate.c

index c8077e9..58b3af6 100644 (file)
@@ -57,6 +57,8 @@ extern int migrate_huge_page_move_mapping(struct address_space *mapping,
                                  struct page *newpage, struct page *page);
 extern int migrate_page_move_mapping(struct address_space *mapping,
                struct page *newpage, struct page *page, int extra_count);
+int folio_migrate_mapping(struct address_space *mapping,
+               struct folio *newfolio, struct folio *folio, int extra_count);
 #else
 
 static inline void putback_movable_pages(struct list_head *l) {}
index a374747..d883d96 100644 (file)
@@ -4,6 +4,7 @@
  * eventually.
  */
 
+#include <linux/migrate.h>
 #include <linux/pagemap.h>
 #include <linux/swap.h>
 
@@ -48,3 +49,13 @@ void mark_page_accessed(struct page *page)
        folio_mark_accessed(page_folio(page));
 }
 EXPORT_SYMBOL(mark_page_accessed);
+
+#ifdef CONFIG_MIGRATION
+int migrate_page_move_mapping(struct address_space *mapping,
+               struct page *newpage, struct page *page, int extra_count)
+{
+       return folio_migrate_mapping(mapping, page_folio(newpage),
+                                       page_folio(page), extra_count);
+}
+EXPORT_SYMBOL(migrate_page_move_mapping);
+#endif
index bfb8ba4..0e408ee 100644 (file)
@@ -364,7 +364,7 @@ static int expected_page_refs(struct address_space *mapping, struct page *page)
         */
        expected_count += is_device_private_page(page);
        if (mapping)
-               expected_count += thp_nr_pages(page) + page_has_private(page);
+               expected_count += compound_nr(page) + page_has_private(page);
 
        return expected_count;
 }
@@ -377,74 +377,75 @@ static int expected_page_refs(struct address_space *mapping, struct page *page)
  * 2 for pages with a mapping
  * 3 for pages with a mapping and PagePrivate/PagePrivate2 set.
  */
-int migrate_page_move_mapping(struct address_space *mapping,
-               struct page *newpage, struct page *page, int extra_count)
+int folio_migrate_mapping(struct address_space *mapping,
+               struct folio *newfolio, struct folio *folio, int extra_count)
 {
-       XA_STATE(xas, &mapping->i_pages, page_index(page));
+       XA_STATE(xas, &mapping->i_pages, folio_index(folio));
        struct zone *oldzone, *newzone;
        int dirty;
-       int expected_count = expected_page_refs(mapping, page) + extra_count;
-       int nr = thp_nr_pages(page);
+       int expected_count = expected_page_refs(mapping, &folio->page) + extra_count;
+       long nr = folio_nr_pages(folio);
 
        if (!mapping) {
                /* Anonymous page without mapping */
-               if (page_count(page) != expected_count)
+               if (folio_ref_count(folio) != expected_count)
                        return -EAGAIN;
 
                /* No turning back from here */
-               newpage->index = page->index;
-               newpage->mapping = page->mapping;
-               if (PageSwapBacked(page))
-                       __SetPageSwapBacked(newpage);
+               newfolio->index = folio->index;
+               newfolio->mapping = folio->mapping;
+               if (folio_test_swapbacked(folio))
+                       __folio_set_swapbacked(newfolio);
 
                return MIGRATEPAGE_SUCCESS;
        }
 
-       oldzone = page_zone(page);
-       newzone = page_zone(newpage);
+       oldzone = folio_zone(folio);
+       newzone = folio_zone(newfolio);
 
        xas_lock_irq(&xas);
-       if (page_count(page) != expected_count || xas_load(&xas) != page) {
+       if (folio_ref_count(folio) != expected_count ||
+           xas_load(&xas) != folio) {
                xas_unlock_irq(&xas);
                return -EAGAIN;
        }
 
-       if (!page_ref_freeze(page, expected_count)) {
+       if (!folio_ref_freeze(folio, expected_count)) {
                xas_unlock_irq(&xas);
                return -EAGAIN;
        }
 
        /*
-        * Now we know that no one else is looking at the page:
+        * Now we know that no one else is looking at the folio:
         * no turning back from here.
         */
-       newpage->index = page->index;
-       newpage->mapping = page->mapping;
-       page_ref_add(newpage, nr); /* add cache reference */
-       if (PageSwapBacked(page)) {
-               __SetPageSwapBacked(newpage);
-               if (PageSwapCache(page)) {
-                       SetPageSwapCache(newpage);
-                       set_page_private(newpage, page_private(page));
+       newfolio->index = folio->index;
+       newfolio->mapping = folio->mapping;
+       folio_ref_add(newfolio, nr); /* add cache reference */
+       if (folio_test_swapbacked(folio)) {
+               __folio_set_swapbacked(newfolio);
+               if (folio_test_swapcache(folio)) {
+                       folio_set_swapcache(newfolio);
+                       newfolio->private = folio_get_private(folio);
                }
        } else {
-               VM_BUG_ON_PAGE(PageSwapCache(page), page);
+               VM_BUG_ON_FOLIO(folio_test_swapcache(folio), folio);
        }
 
        /* Move dirty while page refs frozen and newpage not yet exposed */
-       dirty = PageDirty(page);
+       dirty = folio_test_dirty(folio);
        if (dirty) {
-               ClearPageDirty(page);
-               SetPageDirty(newpage);
+               folio_clear_dirty(folio);
+               folio_set_dirty(newfolio);
        }
 
-       xas_store(&xas, newpage);
-       if (PageTransHuge(page)) {
+       xas_store(&xas, newfolio);
+       if (nr > 1) {
                int i;
 
                for (i = 1; i < nr; i++) {
                        xas_next(&xas);
-                       xas_store(&xas, newpage);
+                       xas_store(&xas, newfolio);
                }
        }
 
@@ -453,7 +454,7 @@ int migrate_page_move_mapping(struct address_space *mapping,
         * to one less reference.
         * We know this isn't the last reference.
         */
-       page_ref_unfreeze(page, expected_count - nr);
+       folio_ref_unfreeze(folio, expected_count - nr);
 
        xas_unlock(&xas);
        /* Leave irq disabled to prevent preemption while updating stats */
@@ -472,18 +473,18 @@ int migrate_page_move_mapping(struct address_space *mapping,
                struct lruvec *old_lruvec, *new_lruvec;
                struct mem_cgroup *memcg;
 
-               memcg = page_memcg(page);
+               memcg = folio_memcg(folio);
                old_lruvec = mem_cgroup_lruvec(memcg, oldzone->zone_pgdat);
                new_lruvec = mem_cgroup_lruvec(memcg, newzone->zone_pgdat);
 
                __mod_lruvec_state(old_lruvec, NR_FILE_PAGES, -nr);
                __mod_lruvec_state(new_lruvec, NR_FILE_PAGES, nr);
-               if (PageSwapBacked(page) && !PageSwapCache(page)) {
+               if (folio_test_swapbacked(folio) && !folio_test_swapcache(folio)) {
                        __mod_lruvec_state(old_lruvec, NR_SHMEM, -nr);
                        __mod_lruvec_state(new_lruvec, NR_SHMEM, nr);
                }
 #ifdef CONFIG_SWAP
-               if (PageSwapCache(page)) {
+               if (folio_test_swapcache(folio)) {
                        __mod_lruvec_state(old_lruvec, NR_SWAPCACHE, -nr);
                        __mod_lruvec_state(new_lruvec, NR_SWAPCACHE, nr);
                }
@@ -499,11 +500,11 @@ int migrate_page_move_mapping(struct address_space *mapping,
 
        return MIGRATEPAGE_SUCCESS;
 }
-EXPORT_SYMBOL(migrate_page_move_mapping);
+EXPORT_SYMBOL(folio_migrate_mapping);
 
 /*
  * The expected number of remaining references is the same as that
- * of migrate_page_move_mapping().
+ * of folio_migrate_mapping().
  */
 int migrate_huge_page_move_mapping(struct address_space *mapping,
                                   struct page *newpage, struct page *page)
@@ -564,7 +565,7 @@ void migrate_page_states(struct page *newpage, struct page *page)
        if (PageMappedToDisk(page))
                SetPageMappedToDisk(newpage);
 
-       /* Move dirty on pages not done by migrate_page_move_mapping() */
+       /* Move dirty on pages not done by folio_migrate_mapping() */
        if (PageDirty(page))
                SetPageDirty(newpage);
 
@@ -640,11 +641,13 @@ int migrate_page(struct address_space *mapping,
                struct page *newpage, struct page *page,
                enum migrate_mode mode)
 {
+       struct folio *newfolio = page_folio(newpage);
+       struct folio *folio = page_folio(page);
        int rc;
 
-       BUG_ON(PageWriteback(page));    /* Writeback must be complete */
+       BUG_ON(folio_test_writeback(folio));    /* Writeback must be complete */
 
-       rc = migrate_page_move_mapping(mapping, newpage, page, 0);
+       rc = folio_migrate_mapping(mapping, newfolio, folio, 0);
 
        if (rc != MIGRATEPAGE_SUCCESS)
                return rc;
@@ -2470,7 +2473,7 @@ static void migrate_vma_collect(struct migrate_vma *migrate)
  * @page: struct page to check
  *
  * Pinned pages cannot be migrated. This is the same test as in
- * migrate_page_move_mapping(), except that here we allow migration of a
+ * folio_migrate_mapping(), except that here we allow migration of a
  * ZONE_DEVICE page.
  */
 static bool migrate_vma_check_page(struct page *page)