fs: Add aops->migrate_folio
authorMatthew Wilcox (Oracle) <willy@infradead.org>
Mon, 6 Jun 2022 13:00:16 +0000 (09:00 -0400)
committerMatthew Wilcox (Oracle) <willy@infradead.org>
Tue, 2 Aug 2022 16:34:03 +0000 (12:34 -0400)
Provide a folio-based replacement for aops->migratepage.  Update the
documentation to document migrate_folio instead of migratepage.

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Documentation/filesystems/locking.rst
Documentation/filesystems/vfs.rst
include/linux/fs.h
mm/compaction.c
mm/migrate.c

index 9963d9600b717265fe3808f0bb84177bab788c0a..4bb2627026ec8342d25c69a64d32e0f5f68f7f50 100644 (file)
@@ -252,7 +252,8 @@ prototypes::
        bool (*release_folio)(struct folio *, gfp_t);
        void (*free_folio)(struct folio *);
        int (*direct_IO)(struct kiocb *, struct iov_iter *iter);
-       int (*migratepage)(struct address_space *, struct page *, struct page *);
+       int (*migrate_folio)(struct address_space *, struct folio *dst,
+                       struct folio *src, enum migrate_mode);
        int (*launder_folio)(struct folio *);
        bool (*is_partially_uptodate)(struct folio *, size_t from, size_t count);
        int (*error_remove_page)(struct address_space *, struct page *);
@@ -278,7 +279,7 @@ invalidate_folio:   yes                                     exclusive
 release_folio:         yes
 free_folio:            yes
 direct_IO:
-migratepage:           yes (both)
+migrate_folio:         yes (both)
 launder_folio:         yes
 is_partially_uptodate: yes
 error_remove_page:     yes
index b51665cdabc46a8c31478aa698b635617f128a23..6cd6953e175b360c9ee7c70cb0a45d5b2b531516 100644 (file)
@@ -737,8 +737,8 @@ cache in your filesystem.  The following members are defined:
                bool (*release_folio)(struct folio *, gfp_t);
                void (*free_folio)(struct folio *);
                ssize_t (*direct_IO)(struct kiocb *, struct iov_iter *iter);
-               /* migrate the contents of a page to the specified target */
-               int (*migratepage) (struct page *, struct page *);
+               int (*migrate_folio)(struct mapping *, struct folio *dst,
+                               struct folio *src, enum migrate_mode);
                int (*launder_folio) (struct folio *);
 
                bool (*is_partially_uptodate) (struct folio *, size_t from,
@@ -926,12 +926,12 @@ cache in your filesystem.  The following members are defined:
        data directly between the storage and the application's address
        space.
 
-``migrate_page``
+``migrate_folio``
        This is used to compact the physical memory usage.  If the VM
-       wants to relocate a page (maybe off a memory card that is
-       signalling imminent failure) it will pass a new page and an old
-       page to this function.  migrate_page should transfer any private
-       data across and update any references that it has to the page.
+       wants to relocate a folio (maybe from a memory device that is
+       signalling imminent failure) it will pass a new folio and an old
+       folio to this function.  migrate_folio should transfer any private
+       data across and update any references that it has to the folio.
 
 ``launder_folio``
        Called before freeing a folio - it writes back the dirty folio.
index 5d8ee3155ca2e5c4ceda375b1a1d23d9dd7691d0..47431cf8fbb3d4d811bfa49812fd6988a0633bfa 100644 (file)
@@ -362,9 +362,11 @@ struct address_space_operations {
        void (*free_folio)(struct folio *folio);
        ssize_t (*direct_IO)(struct kiocb *, struct iov_iter *iter);
        /*
-        * migrate the contents of a page to the specified target. If
+        * migrate the contents of a folio to the specified target. If
         * migrate_mode is MIGRATE_ASYNC, it must not block.
         */
+       int (*migrate_folio)(struct address_space *, struct folio *dst,
+                       struct folio *src, enum migrate_mode);
        int (*migratepage) (struct address_space *,
                        struct page *, struct page *, enum migrate_mode);
        int (*launder_folio)(struct folio *);
index f23efba1d118cb827a5061f7d88c1837d12b7fdb..458f49f9ab09b52b1a17191ae7006df1caf00d91 100644 (file)
@@ -1042,7 +1042,9 @@ isolate_migratepages_block(struct compact_control *cc, unsigned long low_pfn,
                                goto isolate_fail_put;
 
                        mapping = page_mapping(page);
-                       migrate_dirty = !mapping || mapping->a_ops->migratepage;
+                       migrate_dirty = !mapping ||
+                                       mapping->a_ops->migrate_folio ||
+                                       mapping->a_ops->migratepage;
                        unlock_page(page);
                        if (!migrate_dirty)
                                goto isolate_fail_put;
index 491f03747832470c3ddbf7dc7e8bf52976907e25..3c3c168097dd502377134fc09914aadcbb6bac85 100644 (file)
@@ -856,14 +856,17 @@ static int move_to_new_folio(struct folio *dst, struct folio *src,
 
                if (!mapping)
                        rc = migrate_page(mapping, &dst->page, &src->page, mode);
-               else if (mapping->a_ops->migratepage)
+               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->migrate_folio(mapping, dst, src,
+                                                               mode);
+               else if (mapping->a_ops->migratepage)
                        rc = mapping->a_ops->migratepage(mapping, &dst->page,
                                                        &src->page, mode);
                else