Merge tag 'mm-stable-2022-08-03' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux-2.6-microblaze.git] / mm / migrate.c
index 1649270..6a1597c 100644 (file)
@@ -59,7 +59,7 @@
 
 int isolate_movable_page(struct page *page, isolate_mode_t mode)
 {
-       struct address_space *mapping;
+       const struct movable_operations *mops;
 
        /*
         * Avoid burning cycles with pages that are yet under __free_pages(),
@@ -97,10 +97,10 @@ int isolate_movable_page(struct page *page, isolate_mode_t mode)
        if (!PageMovable(page) || PageIsolated(page))
                goto out_no_isolated;
 
-       mapping = page_mapping(page);
-       VM_BUG_ON_PAGE(!mapping, page);
+       mops = page_movable_ops(page);
+       VM_BUG_ON_PAGE(!mops, page);
 
-       if (!mapping->a_ops->isolate_page(page, mode))
+       if (!mops->isolate_page(page, mode))
                goto out_no_isolated;
 
        /* Driver shouldn't use PG_isolated bit of page->flags */
@@ -120,10 +120,9 @@ out:
 
 static void putback_movable_page(struct page *page)
 {
-       struct address_space *mapping;
+       const struct movable_operations *mops = page_movable_ops(page);
 
-       mapping = page_mapping(page);
-       mapping->a_ops->putback_page(page);
+       mops->putback_page(page);
        ClearPageIsolated(page);
 }
 
@@ -352,13 +351,18 @@ unlock:
 }
 #endif
 
-static int expected_page_refs(struct address_space *mapping, struct page *page)
+static int folio_expected_refs(struct address_space *mapping,
+               struct folio *folio)
 {
-       int expected_count = 1;
+       int refs = 1;
+       if (!mapping)
+               return refs;
 
-       if (mapping)
-               expected_count += compound_nr(page) + page_has_private(page);
-       return expected_count;
+       refs += folio_nr_pages(folio);
+       if (folio_test_private(folio))
+               refs++;
+
+       return refs;
 }
 
 /*
@@ -375,7 +379,7 @@ int folio_migrate_mapping(struct address_space *mapping,
        XA_STATE(xas, &mapping->i_pages, folio_index(folio));
        struct zone *oldzone, *newzone;
        int dirty;
-       int expected_count = expected_page_refs(mapping, &folio->page) + extra_count;
+       int expected_count = folio_expected_refs(mapping, folio) + extra_count;
        long nr = folio_nr_pages(folio);
 
        if (!mapping) {
@@ -485,26 +489,26 @@ EXPORT_SYMBOL(folio_migrate_mapping);
  * of folio_migrate_mapping().
  */
 int migrate_huge_page_move_mapping(struct address_space *mapping,
-                                  struct page *newpage, struct page *page)
+                                  struct folio *dst, struct folio *src)
 {
-       XA_STATE(xas, &mapping->i_pages, page_index(page));
+       XA_STATE(xas, &mapping->i_pages, folio_index(src));
        int expected_count;
 
        xas_lock_irq(&xas);
-       expected_count = 2 + page_has_private(page);
-       if (!page_ref_freeze(page, expected_count)) {
+       expected_count = 2 + folio_has_private(src);
+       if (!folio_ref_freeze(src, expected_count)) {
                xas_unlock_irq(&xas);
                return -EAGAIN;
        }
 
-       newpage->index = page->index;
-       newpage->mapping = page->mapping;
+       dst->index = src->index;
+       dst->mapping = src->mapping;
 
-       get_page(newpage);
+       folio_get(dst);
 
-       xas_store(&xas, newpage);
+       xas_store(&xas, dst);
 
-       page_ref_unfreeze(page, expected_count - 1);
+       folio_ref_unfreeze(src, expected_count - 1);
 
        xas_unlock_irq(&xas);
 
@@ -604,34 +608,37 @@ EXPORT_SYMBOL(folio_migrate_copy);
  *                    Migration functions
  ***********************************************************/
 
-/*
- * Common logic to directly migrate a single LRU page suitable for
- * pages that do not use PagePrivate/PagePrivate2.
+/**
+ * migrate_folio() - Simple folio migration.
+ * @mapping: The address_space containing the folio.
+ * @dst: The folio to migrate the data to.
+ * @src: The folio containing the current data.
+ * @mode: How to migrate the page.
+ *
+ * Common logic to directly migrate a single LRU folio suitable for
+ * folios that do not use PagePrivate/PagePrivate2.
  *
- * Pages are locked upon entry and exit.
+ * Folios are locked upon entry and exit.
  */
-int migrate_page(struct address_space *mapping,
-               struct page *newpage, struct page *page,
-               enum migrate_mode mode)
+int migrate_folio(struct address_space *mapping, struct folio *dst,
+               struct folio *src, enum migrate_mode mode)
 {
-       struct folio *newfolio = page_folio(newpage);
-       struct folio *folio = page_folio(page);
        int rc;
 
-       BUG_ON(folio_test_writeback(folio));    /* Writeback must be complete */
+       BUG_ON(folio_test_writeback(src));      /* Writeback must be complete */
 
-       rc = folio_migrate_mapping(mapping, newfolio, folio, 0);
+       rc = folio_migrate_mapping(mapping, dst, src, 0);
 
        if (rc != MIGRATEPAGE_SUCCESS)
                return rc;
 
        if (mode != MIGRATE_SYNC_NO_COPY)
-               folio_migrate_copy(newfolio, folio);
+               folio_migrate_copy(dst, src);
        else
-               folio_migrate_flags(newfolio, folio);
+               folio_migrate_flags(dst, src);
        return MIGRATEPAGE_SUCCESS;
 }
-EXPORT_SYMBOL(migrate_page);
+EXPORT_SYMBOL(migrate_folio);
 
 #ifdef CONFIG_BLOCK
 /* Returns true if all buffers are successfully locked */
@@ -672,23 +679,23 @@ static bool buffer_migrate_lock_buffers(struct buffer_head *head,
        return true;
 }
 
-static int __buffer_migrate_page(struct address_space *mapping,
-               struct page *newpage, struct page *page, enum migrate_mode mode,
+static int __buffer_migrate_folio(struct address_space *mapping,
+               struct folio *dst, struct folio *src, enum migrate_mode mode,
                bool check_refs)
 {
        struct buffer_head *bh, *head;
        int rc;
        int expected_count;
 
-       if (!page_has_buffers(page))
-               return migrate_page(mapping, newpage, page, mode);
+       head = folio_buffers(src);
+       if (!head)
+               return migrate_folio(mapping, dst, src, mode);
 
        /* Check whether page does not have extra refs before we do more work */
-       expected_count = expected_page_refs(mapping, page);
-       if (page_count(page) != expected_count)
+       expected_count = folio_expected_refs(mapping, src);
+       if (folio_ref_count(src) != expected_count)
                return -EAGAIN;
 
-       head = page_buffers(page);
        if (!buffer_migrate_lock_buffers(head, mode))
                return -EAGAIN;
 
@@ -719,23 +726,22 @@ recheck_buffers:
                }
        }
 
-       rc = migrate_page_move_mapping(mapping, newpage, page, 0);
+       rc = folio_migrate_mapping(mapping, dst, src, 0);
        if (rc != MIGRATEPAGE_SUCCESS)
                goto unlock_buffers;
 
-       attach_page_private(newpage, detach_page_private(page));
+       folio_attach_private(dst, folio_detach_private(src));
 
        bh = head;
        do {
-               set_bh_page(bh, newpage, bh_offset(bh));
+               set_bh_page(bh, &dst->page, bh_offset(bh));
                bh = bh->b_this_page;
-
        } while (bh != head);
 
        if (mode != MIGRATE_SYNC_NO_COPY)
-               migrate_page_copy(newpage, page);
+               folio_migrate_copy(dst, src);
        else
-               migrate_page_states(newpage, page);
+               folio_migrate_flags(dst, src);
 
        rc = MIGRATEPAGE_SUCCESS;
 unlock_buffers:
@@ -745,43 +751,79 @@ unlock_buffers:
        do {
                unlock_buffer(bh);
                bh = bh->b_this_page;
-
        } while (bh != head);
 
        return rc;
 }
 
-/*
- * Migration function for pages with buffers. This function can only be used
- * if the underlying filesystem guarantees that no other references to "page"
- * exist. For example attached buffer heads are accessed only under page lock.
+/**
+ * buffer_migrate_folio() - Migration function for folios with buffers.
+ * @mapping: The address space containing @src.
+ * @dst: The folio to migrate to.
+ * @src: The folio to migrate from.
+ * @mode: How to migrate the folio.
+ *
+ * This function can only be used if the underlying filesystem guarantees
+ * that no other references to @src exist. For example attached buffer
+ * heads are accessed only under the folio lock.  If your filesystem cannot
+ * provide this guarantee, buffer_migrate_folio_norefs() may be more
+ * appropriate.
+ *
+ * Return: 0 on success or a negative errno on failure.
  */
-int buffer_migrate_page(struct address_space *mapping,
-               struct page *newpage, struct page *page, enum migrate_mode mode)
+int buffer_migrate_folio(struct address_space *mapping,
+               struct folio *dst, struct folio *src, enum migrate_mode mode)
 {
-       return __buffer_migrate_page(mapping, newpage, page, mode, false);
+       return __buffer_migrate_folio(mapping, dst, src, mode, false);
 }
-EXPORT_SYMBOL(buffer_migrate_page);
+EXPORT_SYMBOL(buffer_migrate_folio);
 
-/*
- * Same as above except that this variant is more careful and checks that there
- * are also no buffer head references. This function is the right one for
- * mappings where buffer heads are directly looked up and referenced (such as
- * block device mappings).
+/**
+ * buffer_migrate_folio_norefs() - Migration function for folios with buffers.
+ * @mapping: The address space containing @src.
+ * @dst: The folio to migrate to.
+ * @src: The folio to migrate from.
+ * @mode: How to migrate the folio.
+ *
+ * Like buffer_migrate_folio() except that this variant is more careful
+ * and checks that there are also no buffer head references. This function
+ * is the right one for mappings where buffer heads are directly looked
+ * up and referenced (such as block device mappings).
+ *
+ * Return: 0 on success or a negative errno on failure.
  */
-int buffer_migrate_page_norefs(struct address_space *mapping,
-               struct page *newpage, struct page *page, enum migrate_mode mode)
+int buffer_migrate_folio_norefs(struct address_space *mapping,
+               struct folio *dst, struct folio *src, enum migrate_mode mode)
 {
-       return __buffer_migrate_page(mapping, newpage, page, mode, true);
+       return __buffer_migrate_folio(mapping, dst, src, mode, true);
 }
 #endif
 
+int filemap_migrate_folio(struct address_space *mapping,
+               struct folio *dst, struct folio *src, enum migrate_mode mode)
+{
+       int ret;
+
+       ret = folio_migrate_mapping(mapping, dst, src, 0);
+       if (ret != MIGRATEPAGE_SUCCESS)
+               return ret;
+
+       if (folio_get_private(src))
+               folio_attach_private(dst, folio_detach_private(src));
+
+       if (mode != MIGRATE_SYNC_NO_COPY)
+               folio_migrate_copy(dst, src);
+       else
+               folio_migrate_flags(dst, src);
+       return MIGRATEPAGE_SUCCESS;
+}
+EXPORT_SYMBOL_GPL(filemap_migrate_folio);
+
 /*
- * Writeback a page to clean the dirty state
+ * Writeback a folio to clean the dirty state
  */
-static int writeout(struct address_space *mapping, struct page *page)
+static int writeout(struct address_space *mapping, struct folio *folio)
 {
-       struct folio *folio = page_folio(page);
        struct writeback_control wbc = {
                .sync_mode = WB_SYNC_NONE,
                .nr_to_write = 1,
@@ -795,25 +837,25 @@ static int writeout(struct address_space *mapping, struct page *page)
                /* No write method for the address space */
                return -EINVAL;
 
-       if (!clear_page_dirty_for_io(page))
+       if (!folio_clear_dirty_for_io(folio))
                /* Someone else already triggered a write */
                return -EAGAIN;
 
        /*
-        * A dirty page may imply that the underlying filesystem has
-        * the page on some queue. So the page must be clean for
-        * migration. Writeout may mean we loose the lock and the
-        * page state is no longer what we checked for earlier.
+        * A dirty folio may imply that the underlying filesystem has
+        * the folio on some queue. So the folio must be clean for
+        * migration. Writeout may mean we lose the lock and the
+        * folio state is no longer what we checked for earlier.
         * At this point we know that the migration attempt cannot
         * be successful.
         */
        remove_migration_ptes(folio, folio, false);
 
-       rc = mapping->a_ops->writepage(page, &wbc);
+       rc = mapping->a_ops->writepage(&folio->page, &wbc);
 
        if (rc != AOP_WRITEPAGE_ACTIVATE)
                /* unlocked. Relock */
-               lock_page(page);
+               folio_lock(folio);
 
        return (rc < 0) ? -EIO : -EAGAIN;
 }
@@ -821,11 +863,11 @@ static int writeout(struct address_space *mapping, struct page *page)
 /*
  * Default handling if a filesystem does not provide a migration function.
  */
-static int fallback_migrate_page(struct address_space *mapping,
-       struct page *newpage, struct page *page, enum migrate_mode mode)
+static int fallback_migrate_folio(struct address_space *mapping,
+               struct folio *dst, struct folio *src, enum migrate_mode mode)
 {
-       if (PageDirty(page)) {
-               /* Only writeback pages in full synchronous migration */
+       if (folio_test_dirty(src)) {
+               /* Only writeback folios in full synchronous migration */
                switch (mode) {
                case MIGRATE_SYNC:
                case MIGRATE_SYNC_NO_COPY:
@@ -833,18 +875,18 @@ static int fallback_migrate_page(struct address_space *mapping,
                default:
                        return -EBUSY;
                }
-               return writeout(mapping, page);
+               return writeout(mapping, src);
        }
 
        /*
         * Buffers may be managed in a filesystem specific way.
         * We must have no buffers or drop them.
         */
-       if (page_has_private(page) &&
-           !try_to_release_page(page, GFP_KERNEL))
+       if (folio_test_private(src) &&
+           !filemap_release_folio(src, GFP_KERNEL))
                return mode == MIGRATE_SYNC ? -EAGAIN : -EBUSY;
 
-       return migrate_page(mapping, newpage, page, mode);
+       return migrate_folio(mapping, dst, src, mode);
 }
 
 /*
@@ -861,32 +903,32 @@ static int fallback_migrate_page(struct address_space *mapping,
 static int move_to_new_folio(struct folio *dst, struct folio *src,
                                enum migrate_mode mode)
 {
-       struct address_space *mapping;
        int rc = -EAGAIN;
        bool is_lru = !__PageMovable(&src->page);
 
        VM_BUG_ON_FOLIO(!folio_test_locked(src), src);
        VM_BUG_ON_FOLIO(!folio_test_locked(dst), dst);
 
-       mapping = folio_mapping(src);
-
        if (likely(is_lru)) {
+               struct address_space *mapping = folio_mapping(src);
+
                if (!mapping)
-                       rc = migrate_page(mapping, &dst->page, &src->page, mode);
-               else if (mapping->a_ops->migratepage)
+                       rc = migrate_folio(mapping, dst, src, mode);
+               else if (mapping->a_ops->migrate_folio)
                        /*
-                        * Most pages have a mapping and most filesystems
-                        * provide a migratepage callback. Anonymous pages
+                        * Most folios have a mapping and most filesystems
+                        * provide a migrate_folio callback. Anonymous folios
                         * are part of swap space which also has its own
-                        * migratepage callback. This is the most common path
+                        * migrate_folio callback. This is the most common path
                         * for page migration.
                         */
-                       rc = mapping->a_ops->migratepage(mapping, &dst->page,
-                                                       &src->page, mode);
+                       rc = mapping->a_ops->migrate_folio(mapping, dst, src,
+                                                               mode);
                else
-                       rc = fallback_migrate_page(mapping, &dst->page,
-                                                       &src->page, mode);
+                       rc = fallback_migrate_folio(mapping, dst, src, mode);
        } else {
+               const struct movable_operations *mops;
+
                /*
                 * In case of non-lru page, it could be released after
                 * isolation step. In that case, we shouldn't try migration.
@@ -898,8 +940,8 @@ static int move_to_new_folio(struct folio *dst, struct folio *src,
                        goto out;
                }
 
-               rc = mapping->a_ops->migratepage(mapping, &dst->page,
-                                               &src->page, mode);
+               mops = page_movable_ops(&src->page);
+               rc = mops->migrate_page(&dst->page, &src->page, mode);
                WARN_ON_ONCE(rc == MIGRATEPAGE_SUCCESS &&
                                !folio_test_isolated(src));
        }