If we add a migrate_folio operation, we can convert the writepage
operation to writepages.  The large folio support here is illusory;
we would need to kmap each page in turn for proper support.  But we do
remove a few hidden calls to compound_head().

Signed-off-by: Matthew Wilcox (Oracle) <wi...@infradead.org>
---
 fs/hostfs/hostfs_kern.c | 54 +++++++++++++++++++----------------------
 1 file changed, 25 insertions(+), 29 deletions(-)

diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
index 7e51d2cec64b..844c45253452 100644
--- a/fs/hostfs/hostfs_kern.c
+++ b/fs/hostfs/hostfs_kern.c
@@ -410,38 +410,33 @@ static const struct file_operations hostfs_dir_fops = {
        .fsync          = hostfs_fsync,
 };
 
-static int hostfs_writepage(struct page *page, struct writeback_control *wbc)
+static int hostfs_writepages(struct address_space *mapping,
+               struct writeback_control *wbc)
 {
-       struct address_space *mapping = page->mapping;
        struct inode *inode = mapping->host;
-       char *buffer;
-       loff_t base = page_offset(page);
-       int count = PAGE_SIZE;
-       int end_index = inode->i_size >> PAGE_SHIFT;
-       int err;
-
-       if (page->index >= end_index)
-               count = inode->i_size & (PAGE_SIZE-1);
-
-       buffer = kmap_local_page(page);
-
-       err = write_file(HOSTFS_I(inode)->fd, &base, buffer, count);
-       if (err != count) {
-               if (err >= 0)
-                       err = -EIO;
-               mapping_set_error(mapping, err);
-               goto out;
+       struct folio *folio = NULL;
+       loff_t i_size = i_size_read(inode);
+       int err = 0;
+
+       while ((folio = writeback_iter(mapping, wbc, folio, &err))) {
+               loff_t pos = folio_pos(folio);
+               size_t count = folio_size(folio);
+               char *buffer;
+               int ret;
+
+               if (count > i_size - pos)
+                       count = i_size - pos;
+
+               buffer = kmap_local_folio(folio, 0);
+               ret = write_file(HOSTFS_I(inode)->fd, &pos, buffer, count);
+               kunmap_local(buffer);
+               folio_unlock(folio);
+               if (ret != count) {
+                       err = ret < 0 ? ret : -EIO;
+                       mapping_set_error(mapping, err);
+               }
        }
 
-       if (base > inode->i_size)
-               inode->i_size = base;
-
-       err = 0;
-
- out:
-       kunmap_local(buffer);
-       unlock_page(page);
-
        return err;
 }
 
@@ -506,11 +501,12 @@ static int hostfs_write_end(struct file *file, struct 
address_space *mapping,
 }
 
 static const struct address_space_operations hostfs_aops = {
-       .writepage      = hostfs_writepage,
+       .writepages     = hostfs_writepages,
        .read_folio     = hostfs_read_folio,
        .dirty_folio    = filemap_dirty_folio,
        .write_begin    = hostfs_write_begin,
        .write_end      = hostfs_write_end,
+       .migrate_folio  = filemap_migrate_folio,
 };
 
 static int hostfs_inode_update(struct inode *ino, const struct hostfs_stat *st)
-- 
2.45.2


Reply via email to