linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/23] Convert write_begin / write_end to take a folio
@ 2024-07-17 15:46 Matthew Wilcox (Oracle)
  2024-07-17 15:46 ` [PATCH 01/23] reiserfs: Convert grab_tail_page() to use " Matthew Wilcox (Oracle)
                   ` (24 more replies)
  0 siblings, 25 replies; 31+ messages in thread
From: Matthew Wilcox (Oracle) @ 2024-07-17 15:46 UTC (permalink / raw)
  To: linux-fsdevel; +Cc: Matthew Wilcox (Oracle)

You can find the full branch at
http://git.infradead.org/?p=users/willy/pagecache.git;a=shortlog;h=refs/heads/write-end
aka
git://git.infradead.org/users/willy/pagecache.git write-end

On top of the ufs, minix, sysv and qnx6 directory handling patches, this
patch series converts us to using folios for write_begin and write_end.
That's the last mention of 'struct page' in several filesystems.

I'd like to get some version of these patches into the 6.12 merge
window.

Matthew Wilcox (Oracle) (23):
  reiserfs: Convert grab_tail_page() to use a folio
  reiserfs: Convert reiserfs_write_begin() to use a folio
  block: Use a folio in blkdev_write_end()
  buffer: Use a folio in generic_write_end()
  nilfs2: Use a folio in nilfs_recover_dsync_blocks()
  ntfs3: Remove reset_log_file()
  buffer: Convert block_write_end() to take a folio
  ecryptfs: Convert ecryptfs_write_end() to use a folio
  ecryptfs: Use a folio in ecryptfs_write_begin()
  f2fs: Convert f2fs_write_end() to use a folio
  f2fs: Convert f2fs_write_begin() to use a folio
  fuse: Convert fuse_write_end() to use a folio
  fuse: Convert fuse_write_begin() to use a folio
  hostfs: Convert hostfs_write_end() to use a folio
  jffs2: Convert jffs2_write_end() to use a folio
  jffs2: Convert jffs2_write_begin() to use a folio
  orangefs: Convert orangefs_write_end() to use a folio
  orangefs: Convert orangefs_write_begin() to use a folio
  vboxsf: Use a folio in vboxsf_write_end()
  fs: Convert aops->write_end to take a folio
  fs: Convert aops->write_begin to take a folio
  ocfs2: Convert ocfs2_write_zero_page to use a folio
  buffer: Convert __block_write_begin() to take a folio

 Documentation/filesystems/locking.rst     |  6 +-
 Documentation/filesystems/vfs.rst         | 12 ++--
 block/fops.c                              | 12 ++--
 drivers/gpu/drm/i915/gem/i915_gem_shmem.c | 47 ++++++------
 fs/adfs/inode.c                           |  5 +-
 fs/affs/file.c                            | 22 +++---
 fs/bcachefs/fs-io-buffered.c              |  8 +--
 fs/bcachefs/fs-io-buffered.h              |  6 +-
 fs/bfs/file.c                             |  4 +-
 fs/buffer.c                               | 46 ++++++------
 fs/ceph/addr.c                            | 13 ++--
 fs/ecryptfs/mmap.c                        | 86 +++++++++++-----------
 fs/exfat/file.c                           |  8 +--
 fs/exfat/inode.c                          |  9 ++-
 fs/ext2/dir.c                             |  4 +-
 fs/ext2/inode.c                           |  8 +--
 fs/ext4/ext4.h                            |  4 +-
 fs/ext4/inline.c                          | 14 ++--
 fs/ext4/inode.c                           | 37 +++++-----
 fs/ext4/verity.c                          |  8 +--
 fs/f2fs/data.c                            | 87 ++++++++++++-----------
 fs/f2fs/super.c                           |  8 +--
 fs/f2fs/verity.c                          |  8 +--
 fs/fat/inode.c                            |  9 ++-
 fs/fuse/file.c                            | 47 ++++++------
 fs/hfs/extent.c                           |  6 +-
 fs/hfs/hfs_fs.h                           |  2 +-
 fs/hfs/inode.c                            |  5 +-
 fs/hfsplus/extents.c                      |  6 +-
 fs/hfsplus/hfsplus_fs.h                   |  2 +-
 fs/hfsplus/inode.c                        |  5 +-
 fs/hostfs/hostfs_kern.c                   | 23 +++---
 fs/hpfs/file.c                            |  9 ++-
 fs/hugetlbfs/inode.c                      |  4 +-
 fs/iomap/buffered-io.c                    |  2 +-
 fs/jffs2/file.c                           | 66 +++++++++--------
 fs/jfs/inode.c                            |  8 +--
 fs/libfs.c                                | 13 ++--
 fs/minix/dir.c                            |  2 +-
 fs/minix/inode.c                          |  6 +-
 fs/namei.c                                | 10 +--
 fs/nfs/file.c                             |  7 +-
 fs/nilfs2/dir.c                           |  4 +-
 fs/nilfs2/inode.c                         | 10 +--
 fs/nilfs2/recovery.c                      | 16 ++---
 fs/ntfs3/file.c                           |  9 ++-
 fs/ntfs3/inode.c                          | 51 ++-----------
 fs/ntfs3/ntfs_fs.h                        |  5 +-
 fs/ocfs2/aops.c                           | 12 ++--
 fs/ocfs2/aops.h                           |  2 +-
 fs/ocfs2/file.c                           | 17 ++---
 fs/ocfs2/mmap.c                           |  6 +-
 fs/omfs/file.c                            |  4 +-
 fs/orangefs/inode.c                       | 39 +++++-----
 fs/reiserfs/inode.c                       | 57 ++++++++-------
 fs/sysv/dir.c                             |  2 +-
 fs/sysv/itree.c                           |  6 +-
 fs/ubifs/file.c                           | 13 ++--
 fs/udf/file.c                             |  2 +-
 fs/udf/inode.c                            | 12 ++--
 fs/ufs/dir.c                              |  2 +-
 fs/ufs/inode.c                            | 10 +--
 fs/vboxsf/file.c                          | 24 +++----
 include/linux/buffer_head.h               | 14 ++--
 include/linux/fs.h                        |  6 +-
 mm/filemap.c                              |  6 +-
 mm/shmem.c                                | 10 ++-
 67 files changed, 482 insertions(+), 551 deletions(-)

-- 
2.43.0


^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 01/23] reiserfs: Convert grab_tail_page() to use a folio
  2024-07-17 15:46 [PATCH 00/23] Convert write_begin / write_end to take a folio Matthew Wilcox (Oracle)
@ 2024-07-17 15:46 ` Matthew Wilcox (Oracle)
  2024-07-17 15:46 ` [PATCH 02/23] reiserfs: Convert reiserfs_write_begin() " Matthew Wilcox (Oracle)
                   ` (23 subsequent siblings)
  24 siblings, 0 replies; 31+ messages in thread
From: Matthew Wilcox (Oracle) @ 2024-07-17 15:46 UTC (permalink / raw)
  To: linux-fsdevel; +Cc: Matthew Wilcox (Oracle)

Removes a call to grab_cache_page() and a few hidden calls to
compound_head().

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
 fs/reiserfs/inode.c | 23 +++++++++++------------
 1 file changed, 11 insertions(+), 12 deletions(-)

diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index 9b43a81a6488..2d558b2012ea 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -2178,7 +2178,7 @@ static int grab_tail_page(struct inode *inode,
 	unsigned long offset = (inode->i_size) & (PAGE_SIZE - 1);
 	struct buffer_head *bh;
 	struct buffer_head *head;
-	struct page *page;
+	struct folio *folio;
 	int error;
 
 	/*
@@ -2190,20 +2190,20 @@ static int grab_tail_page(struct inode *inode,
 	if ((offset & (blocksize - 1)) == 0) {
 		return -ENOENT;
 	}
-	page = grab_cache_page(inode->i_mapping, index);
-	error = -ENOMEM;
-	if (!page) {
-		goto out;
-	}
+	folio = __filemap_get_folio(inode->i_mapping, index,
+			FGP_LOCK | FGP_ACCESSED | FGP_CREAT,
+			mapping_gfp_mask(inode->i_mapping));
+	if (IS_ERR(folio))
+		return PTR_ERR(folio);
 	/* start within the page of the last block in the file */
 	start = (offset / blocksize) * blocksize;
 
-	error = __block_write_begin(page, start, offset - start,
+	error = __block_write_begin(&folio->page, start, offset - start,
 				    reiserfs_get_block_create_0);
 	if (error)
 		goto unlock;
 
-	head = page_buffers(page);
+	head = folio_buffers(folio);
 	bh = head;
 	do {
 		if (pos >= start) {
@@ -2226,14 +2226,13 @@ static int grab_tail_page(struct inode *inode,
 		goto unlock;
 	}
 	*bh_result = bh;
-	*page_result = page;
+	*page_result = &folio->page;
 
-out:
 	return error;
 
 unlock:
-	unlock_page(page);
-	put_page(page);
+	folio_unlock(folio);
+	folio_put(folio);
 	return error;
 }
 
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 02/23] reiserfs: Convert reiserfs_write_begin() to use a folio
  2024-07-17 15:46 [PATCH 00/23] Convert write_begin / write_end to take a folio Matthew Wilcox (Oracle)
  2024-07-17 15:46 ` [PATCH 01/23] reiserfs: Convert grab_tail_page() to use " Matthew Wilcox (Oracle)
@ 2024-07-17 15:46 ` Matthew Wilcox (Oracle)
  2024-07-17 15:46 ` [PATCH 03/23] block: Use a folio in blkdev_write_end() Matthew Wilcox (Oracle)
                   ` (22 subsequent siblings)
  24 siblings, 0 replies; 31+ messages in thread
From: Matthew Wilcox (Oracle) @ 2024-07-17 15:46 UTC (permalink / raw)
  To: linux-fsdevel; +Cc: Matthew Wilcox (Oracle)

Remove a few calls to compound_head().

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
 fs/reiserfs/inode.c | 19 ++++++++++---------
 1 file changed, 10 insertions(+), 9 deletions(-)

diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index 2d558b2012ea..33da519c9767 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -2738,20 +2738,21 @@ static int reiserfs_write_begin(struct file *file,
 				struct page **pagep, void **fsdata)
 {
 	struct inode *inode;
-	struct page *page;
+	struct folio *folio;
 	pgoff_t index;
 	int ret;
 	int old_ref = 0;
 
  	inode = mapping->host;
 	index = pos >> PAGE_SHIFT;
-	page = grab_cache_page_write_begin(mapping, index);
-	if (!page)
-		return -ENOMEM;
-	*pagep = page;
+	folio = __filemap_get_folio(mapping, index, FGP_WRITEBEGIN,
+			mapping_gfp_mask(mapping));
+	if (IS_ERR(folio))
+		return PTR_ERR(folio);
+	*pagep = &folio->page;
 
 	reiserfs_wait_on_write_block(inode->i_sb);
-	fix_tail_page_for_writing(page);
+	fix_tail_page_for_writing(&folio->page);
 	if (reiserfs_transaction_running(inode->i_sb)) {
 		struct reiserfs_transaction_handle *th;
 		th = (struct reiserfs_transaction_handle *)current->
@@ -2761,7 +2762,7 @@ static int reiserfs_write_begin(struct file *file,
 		old_ref = th->t_refcount;
 		th->t_refcount++;
 	}
-	ret = __block_write_begin(page, pos, len, reiserfs_get_block);
+	ret = __block_write_begin(&folio->page, pos, len, reiserfs_get_block);
 	if (ret && reiserfs_transaction_running(inode->i_sb)) {
 		struct reiserfs_transaction_handle *th = current->journal_info;
 		/*
@@ -2791,8 +2792,8 @@ static int reiserfs_write_begin(struct file *file,
 		}
 	}
 	if (ret) {
-		unlock_page(page);
-		put_page(page);
+		folio_unlock(folio);
+		folio_put(folio);
 		/* Truncate allocated blocks */
 		reiserfs_truncate_failed_write(inode);
 	}
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 03/23] block: Use a folio in blkdev_write_end()
  2024-07-17 15:46 [PATCH 00/23] Convert write_begin / write_end to take a folio Matthew Wilcox (Oracle)
  2024-07-17 15:46 ` [PATCH 01/23] reiserfs: Convert grab_tail_page() to use " Matthew Wilcox (Oracle)
  2024-07-17 15:46 ` [PATCH 02/23] reiserfs: Convert reiserfs_write_begin() " Matthew Wilcox (Oracle)
@ 2024-07-17 15:46 ` Matthew Wilcox (Oracle)
  2024-07-17 15:46 ` [PATCH 04/23] buffer: Use a folio in generic_write_end() Matthew Wilcox (Oracle)
                   ` (21 subsequent siblings)
  24 siblings, 0 replies; 31+ messages in thread
From: Matthew Wilcox (Oracle) @ 2024-07-17 15:46 UTC (permalink / raw)
  To: linux-fsdevel; +Cc: Matthew Wilcox (Oracle)

Replaces two hidden calls to compound_head() with one explicit one.

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
 block/fops.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/block/fops.c b/block/fops.c
index 9825c1713a49..da44fedb23e5 100644
--- a/block/fops.c
+++ b/block/fops.c
@@ -460,11 +460,12 @@ static int blkdev_write_end(struct file *file, struct address_space *mapping,
 		loff_t pos, unsigned len, unsigned copied, struct page *page,
 		void *fsdata)
 {
+	struct folio *folio = page_folio(page);
 	int ret;
 	ret = block_write_end(file, mapping, pos, len, copied, page, fsdata);
 
-	unlock_page(page);
-	put_page(page);
+	folio_unlock(folio);
+	folio_put(folio);
 
 	return ret;
 }
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 04/23] buffer: Use a folio in generic_write_end()
  2024-07-17 15:46 [PATCH 00/23] Convert write_begin / write_end to take a folio Matthew Wilcox (Oracle)
                   ` (2 preceding siblings ...)
  2024-07-17 15:46 ` [PATCH 03/23] block: Use a folio in blkdev_write_end() Matthew Wilcox (Oracle)
@ 2024-07-17 15:46 ` Matthew Wilcox (Oracle)
  2024-07-17 15:46 ` [PATCH 05/23] nilfs2: Use a folio in nilfs_recover_dsync_blocks() Matthew Wilcox (Oracle)
                   ` (20 subsequent siblings)
  24 siblings, 0 replies; 31+ messages in thread
From: Matthew Wilcox (Oracle) @ 2024-07-17 15:46 UTC (permalink / raw)
  To: linux-fsdevel; +Cc: Matthew Wilcox (Oracle)

Replaces two implicit calls to compound_head() with one.

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
 fs/buffer.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/fs/buffer.c b/fs/buffer.c
index a9aeb04da398..448338810802 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -2283,6 +2283,7 @@ int generic_write_end(struct file *file, struct address_space *mapping,
 			loff_t pos, unsigned len, unsigned copied,
 			struct page *page, void *fsdata)
 {
+	struct folio *folio = page_folio(page);
 	struct inode *inode = mapping->host;
 	loff_t old_size = inode->i_size;
 	bool i_size_changed = false;
@@ -2293,7 +2294,7 @@ int generic_write_end(struct file *file, struct address_space *mapping,
 	 * No need to use i_size_read() here, the i_size cannot change under us
 	 * because we hold i_rwsem.
 	 *
-	 * But it's important to update i_size while still holding page lock:
+	 * But it's important to update i_size while still holding folio lock:
 	 * page writeout could otherwise come in and zero beyond i_size.
 	 */
 	if (pos + copied > inode->i_size) {
@@ -2301,8 +2302,8 @@ int generic_write_end(struct file *file, struct address_space *mapping,
 		i_size_changed = true;
 	}
 
-	unlock_page(page);
-	put_page(page);
+	folio_unlock(folio);
+	folio_put(folio);
 
 	if (old_size < pos)
 		pagecache_isize_extended(inode, old_size, pos);
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 05/23] nilfs2: Use a folio in nilfs_recover_dsync_blocks()
  2024-07-17 15:46 [PATCH 00/23] Convert write_begin / write_end to take a folio Matthew Wilcox (Oracle)
                   ` (3 preceding siblings ...)
  2024-07-17 15:46 ` [PATCH 04/23] buffer: Use a folio in generic_write_end() Matthew Wilcox (Oracle)
@ 2024-07-17 15:46 ` Matthew Wilcox (Oracle)
  2024-07-18 17:14   ` Ryusuke Konishi
  2024-07-17 15:46 ` [PATCH 06/23] ntfs3: Remove reset_log_file() Matthew Wilcox (Oracle)
                   ` (19 subsequent siblings)
  24 siblings, 1 reply; 31+ messages in thread
From: Matthew Wilcox (Oracle) @ 2024-07-17 15:46 UTC (permalink / raw)
  To: linux-fsdevel; +Cc: Matthew Wilcox (Oracle)

Replaces four hidden calls to compound_head() with one.

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
 fs/nilfs2/recovery.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/fs/nilfs2/recovery.c b/fs/nilfs2/recovery.c
index b638dc06df2f..15653701b1c8 100644
--- a/fs/nilfs2/recovery.c
+++ b/fs/nilfs2/recovery.c
@@ -499,6 +499,7 @@ static int nilfs_recover_dsync_blocks(struct the_nilfs *nilfs,
 	struct nilfs_recovery_block *rb, *n;
 	unsigned int blocksize = nilfs->ns_blocksize;
 	struct page *page;
+	struct folio *folio;
 	loff_t pos;
 	int err = 0, err2 = 0;
 
@@ -522,6 +523,7 @@ static int nilfs_recover_dsync_blocks(struct the_nilfs *nilfs,
 			goto failed_inode;
 		}
 
+		folio = page_folio(page);
 		err = nilfs_recovery_copy_block(nilfs, rb, pos, page);
 		if (unlikely(err))
 			goto failed_page;
@@ -533,15 +535,15 @@ static int nilfs_recover_dsync_blocks(struct the_nilfs *nilfs,
 		block_write_end(NULL, inode->i_mapping, pos, blocksize,
 				blocksize, page, NULL);
 
-		unlock_page(page);
-		put_page(page);
+		folio_unlock(folio);
+		folio_put(folio);
 
 		(*nr_salvaged_blocks)++;
 		goto next;
 
  failed_page:
-		unlock_page(page);
-		put_page(page);
+		folio_unlock(folio);
+		folio_put(folio);
 
  failed_inode:
 		nilfs_warn(sb,
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 06/23] ntfs3: Remove reset_log_file()
  2024-07-17 15:46 [PATCH 00/23] Convert write_begin / write_end to take a folio Matthew Wilcox (Oracle)
                   ` (4 preceding siblings ...)
  2024-07-17 15:46 ` [PATCH 05/23] nilfs2: Use a folio in nilfs_recover_dsync_blocks() Matthew Wilcox (Oracle)
@ 2024-07-17 15:46 ` Matthew Wilcox (Oracle)
  2024-07-17 15:46 ` [PATCH 07/23] buffer: Convert block_write_end() to take a folio Matthew Wilcox (Oracle)
                   ` (18 subsequent siblings)
  24 siblings, 0 replies; 31+ messages in thread
From: Matthew Wilcox (Oracle) @ 2024-07-17 15:46 UTC (permalink / raw)
  To: linux-fsdevel; +Cc: Matthew Wilcox (Oracle)

This function has no callers (which will be why nobody noticed that
the page wasn't being unlocked).

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
 fs/ntfs3/inode.c   | 39 ---------------------------------------
 fs/ntfs3/ntfs_fs.h |  1 -
 2 files changed, 40 deletions(-)

diff --git a/fs/ntfs3/inode.c b/fs/ntfs3/inode.c
index 6b0bdc474e76..8eaaf9e465d4 100644
--- a/fs/ntfs3/inode.c
+++ b/fs/ntfs3/inode.c
@@ -1008,45 +1008,6 @@ int ntfs_write_end(struct file *file, struct address_space *mapping, loff_t pos,
 	return err;
 }
 
-int reset_log_file(struct inode *inode)
-{
-	int err;
-	loff_t pos = 0;
-	u32 log_size = inode->i_size;
-	struct address_space *mapping = inode->i_mapping;
-
-	for (;;) {
-		u32 len;
-		void *kaddr;
-		struct page *page;
-
-		len = pos + PAGE_SIZE > log_size ? (log_size - pos) : PAGE_SIZE;
-
-		err = block_write_begin(mapping, pos, len, &page,
-					ntfs_get_block_write_begin);
-		if (err)
-			goto out;
-
-		kaddr = kmap_atomic(page);
-		memset(kaddr, -1, len);
-		kunmap_atomic(kaddr);
-		flush_dcache_page(page);
-
-		err = block_write_end(NULL, mapping, pos, len, len, page, NULL);
-		if (err < 0)
-			goto out;
-		pos += len;
-
-		if (pos >= log_size)
-			break;
-		balance_dirty_pages_ratelimited(mapping);
-	}
-out:
-	mark_inode_dirty_sync(inode);
-
-	return err;
-}
-
 int ntfs3_write_inode(struct inode *inode, struct writeback_control *wbc)
 {
 	return _ni_write_inode(inode, wbc->sync_mode == WB_SYNC_ALL);
diff --git a/fs/ntfs3/ntfs_fs.h b/fs/ntfs3/ntfs_fs.h
index e5255a251929..4e363b8342d6 100644
--- a/fs/ntfs3/ntfs_fs.h
+++ b/fs/ntfs3/ntfs_fs.h
@@ -708,7 +708,6 @@ int indx_update_dup(struct ntfs_inode *ni, struct ntfs_sb_info *sbi,
 struct inode *ntfs_iget5(struct super_block *sb, const struct MFT_REF *ref,
 			 const struct cpu_str *name);
 int ntfs_set_size(struct inode *inode, u64 new_size);
-int reset_log_file(struct inode *inode);
 int ntfs_get_block(struct inode *inode, sector_t vbn,
 		   struct buffer_head *bh_result, int create);
 int ntfs_write_begin(struct file *file, struct address_space *mapping,
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 07/23] buffer: Convert block_write_end() to take a folio
  2024-07-17 15:46 [PATCH 00/23] Convert write_begin / write_end to take a folio Matthew Wilcox (Oracle)
                   ` (5 preceding siblings ...)
  2024-07-17 15:46 ` [PATCH 06/23] ntfs3: Remove reset_log_file() Matthew Wilcox (Oracle)
@ 2024-07-17 15:46 ` Matthew Wilcox (Oracle)
  2024-07-17 15:46 ` [PATCH 08/23] ecryptfs: Convert ecryptfs_write_end() to use " Matthew Wilcox (Oracle)
                   ` (17 subsequent siblings)
  24 siblings, 0 replies; 31+ messages in thread
From: Matthew Wilcox (Oracle) @ 2024-07-17 15:46 UTC (permalink / raw)
  To: linux-fsdevel; +Cc: Matthew Wilcox (Oracle)

All callers now have a folio, so pass it in instead of converting
from a folio to a page and back to a folio again.  Saves a call
to compound_head().

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
 block/fops.c                | 2 +-
 fs/buffer.c                 | 5 ++---
 fs/ext2/dir.c               | 2 +-
 fs/ext4/inode.c             | 4 ++--
 fs/iomap/buffered-io.c      | 2 +-
 fs/minix/dir.c              | 2 +-
 fs/nilfs2/dir.c             | 2 +-
 fs/nilfs2/recovery.c        | 2 +-
 fs/sysv/dir.c               | 2 +-
 fs/ufs/dir.c                | 2 +-
 include/linux/buffer_head.h | 4 ++--
 11 files changed, 14 insertions(+), 15 deletions(-)

diff --git a/block/fops.c b/block/fops.c
index da44fedb23e5..df0e762cf397 100644
--- a/block/fops.c
+++ b/block/fops.c
@@ -462,7 +462,7 @@ static int blkdev_write_end(struct file *file, struct address_space *mapping,
 {
 	struct folio *folio = page_folio(page);
 	int ret;
-	ret = block_write_end(file, mapping, pos, len, copied, page, fsdata);
+	ret = block_write_end(file, mapping, pos, len, copied, folio, fsdata);
 
 	folio_unlock(folio);
 	folio_put(folio);
diff --git a/fs/buffer.c b/fs/buffer.c
index 448338810802..acba3dfe55d8 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -2247,9 +2247,8 @@ EXPORT_SYMBOL(block_write_begin);
 
 int block_write_end(struct file *file, struct address_space *mapping,
 			loff_t pos, unsigned len, unsigned copied,
-			struct page *page, void *fsdata)
+			struct folio *folio, void *fsdata)
 {
-	struct folio *folio = page_folio(page);
 	size_t start = pos - folio_pos(folio);
 
 	if (unlikely(copied < len)) {
@@ -2288,7 +2287,7 @@ int generic_write_end(struct file *file, struct address_space *mapping,
 	loff_t old_size = inode->i_size;
 	bool i_size_changed = false;
 
-	copied = block_write_end(file, mapping, pos, len, copied, page, fsdata);
+	copied = block_write_end(file, mapping, pos, len, copied, folio, fsdata);
 
 	/*
 	 * No need to use i_size_read() here, the i_size cannot change under us
diff --git a/fs/ext2/dir.c b/fs/ext2/dir.c
index 087457061c6e..60605fbdd0eb 100644
--- a/fs/ext2/dir.c
+++ b/fs/ext2/dir.c
@@ -87,7 +87,7 @@ static void ext2_commit_chunk(struct folio *folio, loff_t pos, unsigned len)
 	struct inode *dir = mapping->host;
 
 	inode_inc_iversion(dir);
-	block_write_end(NULL, mapping, pos, len, len, &folio->page, NULL);
+	block_write_end(NULL, mapping, pos, len, len, folio, NULL);
 
 	if (pos+len > dir->i_size) {
 		i_size_write(dir, pos+len);
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 941c1c0d5c6e..1e4831d83adc 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -1315,7 +1315,7 @@ static int ext4_write_end(struct file *file,
 		return ext4_write_inline_data_end(inode, pos, len, copied,
 						  folio);
 
-	copied = block_write_end(file, mapping, pos, len, copied, page, fsdata);
+	copied = block_write_end(file, mapping, pos, len, copied, folio, fsdata);
 	/*
 	 * it's important to update i_size while still holding folio lock:
 	 * page writeout could otherwise come in and zero beyond i_size.
@@ -3029,7 +3029,7 @@ static int ext4_da_do_write_end(struct address_space *mapping,
 	 * flag, which all that's needed to trigger page writeback.
 	 */
 	copied = block_write_end(NULL, mapping, pos, len, copied,
-			&folio->page, NULL);
+			folio, NULL);
 	new_i_size = pos + copied;
 
 	/*
diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c
index f420c53d86ac..9b4ca3811a24 100644
--- a/fs/iomap/buffered-io.c
+++ b/fs/iomap/buffered-io.c
@@ -900,7 +900,7 @@ static bool iomap_write_end(struct iomap_iter *iter, loff_t pos, size_t len,
 		size_t bh_written;
 
 		bh_written = block_write_end(NULL, iter->inode->i_mapping, pos,
-					len, copied, &folio->page, NULL);
+					len, copied, folio, NULL);
 		WARN_ON_ONCE(bh_written != copied && bh_written != 0);
 		return bh_written == copied;
 	}
diff --git a/fs/minix/dir.c b/fs/minix/dir.c
index 5f9e2fc91003..dd2a425b41f0 100644
--- a/fs/minix/dir.c
+++ b/fs/minix/dir.c
@@ -45,7 +45,7 @@ static void dir_commit_chunk(struct folio *folio, loff_t pos, unsigned len)
 	struct address_space *mapping = folio->mapping;
 	struct inode *dir = mapping->host;
 
-	block_write_end(NULL, mapping, pos, len, len, &folio->page, NULL);
+	block_write_end(NULL, mapping, pos, len, len, folio, NULL);
 
 	if (pos+len > dir->i_size) {
 		i_size_write(dir, pos+len);
diff --git a/fs/nilfs2/dir.c b/fs/nilfs2/dir.c
index 4a29b0138d75..66af42f88ca7 100644
--- a/fs/nilfs2/dir.c
+++ b/fs/nilfs2/dir.c
@@ -96,7 +96,7 @@ static void nilfs_commit_chunk(struct folio *folio,
 	int err;
 
 	nr_dirty = nilfs_page_count_clean_buffers(&folio->page, from, to);
-	copied = block_write_end(NULL, mapping, pos, len, len, &folio->page, NULL);
+	copied = block_write_end(NULL, mapping, pos, len, len, folio, NULL);
 	if (pos + copied > dir->i_size)
 		i_size_write(dir, pos + copied);
 	if (IS_DIRSYNC(dir))
diff --git a/fs/nilfs2/recovery.c b/fs/nilfs2/recovery.c
index 15653701b1c8..40c5dfbc9d41 100644
--- a/fs/nilfs2/recovery.c
+++ b/fs/nilfs2/recovery.c
@@ -533,7 +533,7 @@ static int nilfs_recover_dsync_blocks(struct the_nilfs *nilfs,
 			goto failed_page;
 
 		block_write_end(NULL, inode->i_mapping, pos, blocksize,
-				blocksize, page, NULL);
+				blocksize, folio, NULL);
 
 		folio_unlock(folio);
 		folio_put(folio);
diff --git a/fs/sysv/dir.c b/fs/sysv/dir.c
index 27eaa5273ba7..639307e2ff8c 100644
--- a/fs/sysv/dir.c
+++ b/fs/sysv/dir.c
@@ -33,7 +33,7 @@ static void dir_commit_chunk(struct folio *folio, loff_t pos, unsigned len)
 	struct address_space *mapping = folio->mapping;
 	struct inode *dir = mapping->host;
 
-	block_write_end(NULL, mapping, pos, len, len, &folio->page, NULL);
+	block_write_end(NULL, mapping, pos, len, len, folio, NULL);
 	if (pos+len > dir->i_size) {
 		i_size_write(dir, pos+len);
 		mark_inode_dirty(dir);
diff --git a/fs/ufs/dir.c b/fs/ufs/dir.c
index 3b3cd84f1f7f..1579561118f5 100644
--- a/fs/ufs/dir.c
+++ b/fs/ufs/dir.c
@@ -48,7 +48,7 @@ static void ufs_commit_chunk(struct folio *folio, loff_t pos, unsigned len)
 	struct inode *dir = mapping->host;
 
 	inode_inc_iversion(dir);
-	block_write_end(NULL, mapping, pos, len, len, &folio->page, NULL);
+	block_write_end(NULL, mapping, pos, len, len, folio, NULL);
 	if (pos+len > dir->i_size) {
 		i_size_write(dir, pos+len);
 		mark_inode_dirty(dir);
diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h
index 14acf1bbe0ce..3a3fec154536 100644
--- a/include/linux/buffer_head.h
+++ b/include/linux/buffer_head.h
@@ -262,8 +262,8 @@ int block_write_begin(struct address_space *mapping, loff_t pos, unsigned len,
 int __block_write_begin(struct page *page, loff_t pos, unsigned len,
 		get_block_t *get_block);
 int block_write_end(struct file *, struct address_space *,
-				loff_t, unsigned, unsigned,
-				struct page *, void *);
+				loff_t, unsigned len, unsigned copied,
+				struct folio *, void *);
 int generic_write_end(struct file *, struct address_space *,
 				loff_t, unsigned, unsigned,
 				struct page *, void *);
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 08/23] ecryptfs: Convert ecryptfs_write_end() to use a folio
  2024-07-17 15:46 [PATCH 00/23] Convert write_begin / write_end to take a folio Matthew Wilcox (Oracle)
                   ` (6 preceding siblings ...)
  2024-07-17 15:46 ` [PATCH 07/23] buffer: Convert block_write_end() to take a folio Matthew Wilcox (Oracle)
@ 2024-07-17 15:46 ` Matthew Wilcox (Oracle)
  2024-07-17 15:46 ` [PATCH 09/23] ecryptfs: Use a folio in ecryptfs_write_begin() Matthew Wilcox (Oracle)
                   ` (16 subsequent siblings)
  24 siblings, 0 replies; 31+ messages in thread
From: Matthew Wilcox (Oracle) @ 2024-07-17 15:46 UTC (permalink / raw)
  To: linux-fsdevel; +Cc: Matthew Wilcox (Oracle)

Convert the passed page to a folio and operate on that.
Replaces four calls to compound_head() with one.

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
 fs/ecryptfs/mmap.c | 25 +++++++++++++------------
 1 file changed, 13 insertions(+), 12 deletions(-)

diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c
index e2483acc4366..9b86fad2b9d1 100644
--- a/fs/ecryptfs/mmap.c
+++ b/fs/ecryptfs/mmap.c
@@ -234,17 +234,17 @@ static int ecryptfs_read_folio(struct file *file, struct folio *folio)
 /*
  * Called with lower inode mutex held.
  */
-static int fill_zeros_to_end_of_page(struct page *page, unsigned int to)
+static int fill_zeros_to_end_of_page(struct folio *folio, unsigned int to)
 {
-	struct inode *inode = page->mapping->host;
+	struct inode *inode = folio->mapping->host;
 	int end_byte_in_page;
 
-	if ((i_size_read(inode) / PAGE_SIZE) != page->index)
+	if ((i_size_read(inode) / PAGE_SIZE) != folio->index)
 		goto out;
 	end_byte_in_page = i_size_read(inode) % PAGE_SIZE;
 	if (to > end_byte_in_page)
 		end_byte_in_page = to;
-	zero_user_segment(page, end_byte_in_page, PAGE_SIZE);
+	folio_zero_segment(folio, end_byte_in_page, PAGE_SIZE);
 out:
 	return 0;
 }
@@ -465,6 +465,7 @@ static int ecryptfs_write_end(struct file *file,
 			loff_t pos, unsigned len, unsigned copied,
 			struct page *page, void *fsdata)
 {
+	struct folio *folio = page_folio(page);
 	pgoff_t index = pos >> PAGE_SHIFT;
 	unsigned from = pos & (PAGE_SIZE - 1);
 	unsigned to = from + copied;
@@ -476,8 +477,8 @@ static int ecryptfs_write_end(struct file *file,
 	ecryptfs_printk(KERN_DEBUG, "Calling fill_zeros_to_end_of_page"
 			"(page w/ index = [0x%.16lx], to = [%d])\n", index, to);
 	if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) {
-		rc = ecryptfs_write_lower_page_segment(ecryptfs_inode, page, 0,
-						       to);
+		rc = ecryptfs_write_lower_page_segment(ecryptfs_inode,
+				&folio->page, 0, to);
 		if (!rc) {
 			rc = copied;
 			fsstack_copy_inode_size(ecryptfs_inode,
@@ -485,21 +486,21 @@ static int ecryptfs_write_end(struct file *file,
 		}
 		goto out;
 	}
-	if (!PageUptodate(page)) {
+	if (!folio_test_uptodate(folio)) {
 		if (copied < PAGE_SIZE) {
 			rc = 0;
 			goto out;
 		}
-		SetPageUptodate(page);
+		folio_mark_uptodate(folio);
 	}
 	/* Fills in zeros if 'to' goes beyond inode size */
-	rc = fill_zeros_to_end_of_page(page, to);
+	rc = fill_zeros_to_end_of_page(folio, to);
 	if (rc) {
 		ecryptfs_printk(KERN_WARNING, "Error attempting to fill "
 			"zeros in page with index = [0x%.16lx]\n", index);
 		goto out;
 	}
-	rc = ecryptfs_encrypt_page(page);
+	rc = ecryptfs_encrypt_page(&folio->page);
 	if (rc) {
 		ecryptfs_printk(KERN_WARNING, "Error encrypting page (upper "
 				"index [0x%.16lx])\n", index);
@@ -518,8 +519,8 @@ static int ecryptfs_write_end(struct file *file,
 	else
 		rc = copied;
 out:
-	unlock_page(page);
-	put_page(page);
+	folio_unlock(folio);
+	folio_put(folio);
 	return rc;
 }
 
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 09/23] ecryptfs: Use a folio in ecryptfs_write_begin()
  2024-07-17 15:46 [PATCH 00/23] Convert write_begin / write_end to take a folio Matthew Wilcox (Oracle)
                   ` (7 preceding siblings ...)
  2024-07-17 15:46 ` [PATCH 08/23] ecryptfs: Convert ecryptfs_write_end() to use " Matthew Wilcox (Oracle)
@ 2024-07-17 15:46 ` Matthew Wilcox (Oracle)
  2024-07-17 15:47 ` [PATCH 10/23] f2fs: Convert f2fs_write_end() to use a folio Matthew Wilcox (Oracle)
                   ` (15 subsequent siblings)
  24 siblings, 0 replies; 31+ messages in thread
From: Matthew Wilcox (Oracle) @ 2024-07-17 15:46 UTC (permalink / raw)
  To: linux-fsdevel; +Cc: Matthew Wilcox (Oracle)

Use __filemap_get_folio() instead of grab_cache_page_write_begin()
and use the folio throughout.  No attempt is made here to support
large folios, simply converting this function to use folio APIs is
the goal.  Saves many hidden calls to compound_head().

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
 fs/ecryptfs/mmap.c | 53 +++++++++++++++++++++++-----------------------
 1 file changed, 27 insertions(+), 26 deletions(-)

diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c
index 9b86fad2b9d1..75ce28d757b7 100644
--- a/fs/ecryptfs/mmap.c
+++ b/fs/ecryptfs/mmap.c
@@ -268,35 +268,36 @@ static int ecryptfs_write_begin(struct file *file,
 			struct page **pagep, void **fsdata)
 {
 	pgoff_t index = pos >> PAGE_SHIFT;
-	struct page *page;
+	struct folio *folio;
 	loff_t prev_page_end_size;
 	int rc = 0;
 
-	page = grab_cache_page_write_begin(mapping, index);
-	if (!page)
-		return -ENOMEM;
-	*pagep = page;
+	folio = __filemap_get_folio(mapping, index, FGP_WRITEBEGIN,
+			mapping_gfp_mask(mapping));
+	if (IS_ERR(folio))
+		return PTR_ERR(folio);
+	*pagep = &folio->page;
 
 	prev_page_end_size = ((loff_t)index << PAGE_SHIFT);
-	if (!PageUptodate(page)) {
+	if (!folio_test_uptodate(folio)) {
 		struct ecryptfs_crypt_stat *crypt_stat =
 			&ecryptfs_inode_to_private(mapping->host)->crypt_stat;
 
 		if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) {
 			rc = ecryptfs_read_lower_page_segment(
-				page, index, 0, PAGE_SIZE, mapping->host);
+				&folio->page, index, 0, PAGE_SIZE, mapping->host);
 			if (rc) {
 				printk(KERN_ERR "%s: Error attempting to read "
 				       "lower page segment; rc = [%d]\n",
 				       __func__, rc);
-				ClearPageUptodate(page);
+				folio_clear_uptodate(folio);
 				goto out;
 			} else
-				SetPageUptodate(page);
+				folio_mark_uptodate(folio);
 		} else if (crypt_stat->flags & ECRYPTFS_VIEW_AS_ENCRYPTED) {
 			if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) {
 				rc = ecryptfs_copy_up_encrypted_with_header(
-					page, crypt_stat);
+					&folio->page, crypt_stat);
 				if (rc) {
 					printk(KERN_ERR "%s: Error attempting "
 					       "to copy the encrypted content "
@@ -304,46 +305,46 @@ static int ecryptfs_write_begin(struct file *file,
 					       "inserting the metadata from "
 					       "the xattr into the header; rc "
 					       "= [%d]\n", __func__, rc);
-					ClearPageUptodate(page);
+					folio_clear_uptodate(folio);
 					goto out;
 				}
-				SetPageUptodate(page);
+				folio_mark_uptodate(folio);
 			} else {
 				rc = ecryptfs_read_lower_page_segment(
-					page, index, 0, PAGE_SIZE,
+					&folio->page, index, 0, PAGE_SIZE,
 					mapping->host);
 				if (rc) {
 					printk(KERN_ERR "%s: Error reading "
 					       "page; rc = [%d]\n",
 					       __func__, rc);
-					ClearPageUptodate(page);
+					folio_clear_uptodate(folio);
 					goto out;
 				}
-				SetPageUptodate(page);
+				folio_mark_uptodate(folio);
 			}
 		} else {
 			if (prev_page_end_size
-			    >= i_size_read(page->mapping->host)) {
-				zero_user(page, 0, PAGE_SIZE);
-				SetPageUptodate(page);
+			    >= i_size_read(mapping->host)) {
+				folio_zero_range(folio, 0, PAGE_SIZE);
+				folio_mark_uptodate(folio);
 			} else if (len < PAGE_SIZE) {
-				rc = ecryptfs_decrypt_page(page);
+				rc = ecryptfs_decrypt_page(&folio->page);
 				if (rc) {
 					printk(KERN_ERR "%s: Error decrypting "
 					       "page at index [%ld]; "
 					       "rc = [%d]\n",
-					       __func__, page->index, rc);
-					ClearPageUptodate(page);
+					       __func__, folio->index, rc);
+					folio_clear_uptodate(folio);
 					goto out;
 				}
-				SetPageUptodate(page);
+				folio_mark_uptodate(folio);
 			}
 		}
 	}
 	/* If creating a page or more of holes, zero them out via truncate.
 	 * Note, this will increase i_size. */
 	if (index != 0) {
-		if (prev_page_end_size > i_size_read(page->mapping->host)) {
+		if (prev_page_end_size > i_size_read(mapping->host)) {
 			rc = ecryptfs_truncate(file->f_path.dentry,
 					       prev_page_end_size);
 			if (rc) {
@@ -359,11 +360,11 @@ static int ecryptfs_write_begin(struct file *file,
 	 * of page?  Zero it out. */
 	if ((i_size_read(mapping->host) == prev_page_end_size)
 	    && (pos != 0))
-		zero_user(page, 0, PAGE_SIZE);
+		folio_zero_range(folio, 0, PAGE_SIZE);
 out:
 	if (unlikely(rc)) {
-		unlock_page(page);
-		put_page(page);
+		folio_unlock(folio);
+		folio_put(folio);
 		*pagep = NULL;
 	}
 	return rc;
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 10/23] f2fs: Convert f2fs_write_end() to use a folio
  2024-07-17 15:46 [PATCH 00/23] Convert write_begin / write_end to take a folio Matthew Wilcox (Oracle)
                   ` (8 preceding siblings ...)
  2024-07-17 15:46 ` [PATCH 09/23] ecryptfs: Use a folio in ecryptfs_write_begin() Matthew Wilcox (Oracle)
@ 2024-07-17 15:47 ` Matthew Wilcox (Oracle)
  2024-07-17 15:47 ` [PATCH 11/23] f2fs: Convert f2fs_write_begin() " Matthew Wilcox (Oracle)
                   ` (14 subsequent siblings)
  24 siblings, 0 replies; 31+ messages in thread
From: Matthew Wilcox (Oracle) @ 2024-07-17 15:47 UTC (permalink / raw)
  To: linux-fsdevel; +Cc: Matthew Wilcox (Oracle)

Convert the passed page to a folio and operate on that.
Replaces five calls to compound_head() with one.

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
 fs/f2fs/data.c | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 6457e5bca9c9..58ac23e124a5 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -3687,7 +3687,8 @@ static int f2fs_write_end(struct file *file,
 			loff_t pos, unsigned len, unsigned copied,
 			struct page *page, void *fsdata)
 {
-	struct inode *inode = page->mapping->host;
+	struct folio *folio = page_folio(page);
+	struct inode *inode = folio->mapping->host;
 
 	trace_f2fs_write_end(inode, pos, len, copied);
 
@@ -3696,17 +3697,17 @@ static int f2fs_write_end(struct file *file,
 	 * should be PAGE_SIZE. Otherwise, we treat it with zero copied and
 	 * let generic_perform_write() try to copy data again through copied=0.
 	 */
-	if (!PageUptodate(page)) {
+	if (!folio_test_uptodate(folio)) {
 		if (unlikely(copied != len))
 			copied = 0;
 		else
-			SetPageUptodate(page);
+			folio_mark_uptodate(folio);
 	}
 
 #ifdef CONFIG_F2FS_FS_COMPRESSION
 	/* overwrite compressed file */
 	if (f2fs_compressed_file(inode) && fsdata) {
-		f2fs_compress_write_end(inode, fsdata, page->index, copied);
+		f2fs_compress_write_end(inode, fsdata, folio->index, copied);
 		f2fs_update_time(F2FS_I_SB(inode), REQ_TIME);
 
 		if (pos + copied > i_size_read(inode) &&
@@ -3719,7 +3720,7 @@ static int f2fs_write_end(struct file *file,
 	if (!copied)
 		goto unlock_out;
 
-	set_page_dirty(page);
+	folio_mark_dirty(folio);
 
 	if (pos + copied > i_size_read(inode) &&
 	    !f2fs_verity_in_progress(inode)) {
@@ -3729,7 +3730,8 @@ static int f2fs_write_end(struct file *file,
 					pos + copied);
 	}
 unlock_out:
-	f2fs_put_page(page, 1);
+	folio_unlock(folio);
+	folio_put(folio);
 	f2fs_update_time(F2FS_I_SB(inode), REQ_TIME);
 	return copied;
 }
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 11/23] f2fs: Convert f2fs_write_begin() to use a folio
  2024-07-17 15:46 [PATCH 00/23] Convert write_begin / write_end to take a folio Matthew Wilcox (Oracle)
                   ` (9 preceding siblings ...)
  2024-07-17 15:47 ` [PATCH 10/23] f2fs: Convert f2fs_write_end() to use a folio Matthew Wilcox (Oracle)
@ 2024-07-17 15:47 ` Matthew Wilcox (Oracle)
  2024-07-17 15:47 ` [PATCH 12/23] fuse: Convert fuse_write_end() " Matthew Wilcox (Oracle)
                   ` (13 subsequent siblings)
  24 siblings, 0 replies; 31+ messages in thread
From: Matthew Wilcox (Oracle) @ 2024-07-17 15:47 UTC (permalink / raw)
  To: linux-fsdevel; +Cc: Matthew Wilcox (Oracle)

Fetch a folio from the page cache instead of a page and use it
throughout.  We still have to convert back to a page for calling
internal f2fs functions, but hopefully they will be converted soon.

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
 fs/f2fs/data.c | 66 ++++++++++++++++++++++++++------------------------
 1 file changed, 35 insertions(+), 31 deletions(-)

diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 58ac23e124a5..9a45f9fb8a64 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -3556,8 +3556,8 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping,
 {
 	struct inode *inode = mapping->host;
 	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
-	struct page *page = NULL;
-	pgoff_t index = ((unsigned long long) pos) >> PAGE_SHIFT;
+	struct folio *folio;
+	pgoff_t index = pos >> PAGE_SHIFT;
 	bool need_balance = false;
 	bool use_cow = false;
 	block_t blkaddr = NULL_ADDR;
@@ -3573,7 +3573,7 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping,
 	/*
 	 * We should check this at this moment to avoid deadlock on inode page
 	 * and #0 page. The locking rule for inline_data conversion should be:
-	 * lock_page(page #0) -> lock_page(inode_page)
+	 * folio_lock(folio #0) -> folio_lock(inode_page)
 	 */
 	if (index != 0) {
 		err = f2fs_convert_inline_inode(inode);
@@ -3603,81 +3603,85 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping,
 
 repeat:
 	/*
-	 * Do not use grab_cache_page_write_begin() to avoid deadlock due to
-	 * wait_for_stable_page. Will wait that below with our IO control.
+	 * Do not use FGP_STABLE to avoid deadlock.
+	 * Will wait that below with our IO control.
 	 */
-	page = f2fs_pagecache_get_page(mapping, index,
+	folio = __filemap_get_folio(mapping, index,
 				FGP_LOCK | FGP_WRITE | FGP_CREAT, GFP_NOFS);
-	if (!page) {
-		err = -ENOMEM;
+	if (IS_ERR(folio)) {
+		err = PTR_ERR(folio);
 		goto fail;
 	}
 
 	/* TODO: cluster can be compressed due to race with .writepage */
 
-	*pagep = page;
+	*pagep = &folio->page;
 
 	if (f2fs_is_atomic_file(inode))
-		err = prepare_atomic_write_begin(sbi, page, pos, len,
+		err = prepare_atomic_write_begin(sbi, &folio->page, pos, len,
 					&blkaddr, &need_balance, &use_cow);
 	else
-		err = prepare_write_begin(sbi, page, pos, len,
+		err = prepare_write_begin(sbi, &folio->page, pos, len,
 					&blkaddr, &need_balance);
 	if (err)
-		goto fail;
+		goto put_folio;
 
 	if (need_balance && !IS_NOQUOTA(inode) &&
 			has_not_enough_free_secs(sbi, 0, 0)) {
-		unlock_page(page);
+		folio_unlock(folio);
 		f2fs_balance_fs(sbi, true);
-		lock_page(page);
-		if (page->mapping != mapping) {
-			/* The page got truncated from under us */
-			f2fs_put_page(page, 1);
+		folio_lock(folio);
+		if (folio->mapping != mapping) {
+			/* The folio got truncated from under us */
+			folio_unlock(folio);
+			folio_put(folio);
 			goto repeat;
 		}
 	}
 
-	f2fs_wait_on_page_writeback(page, DATA, false, true);
+	f2fs_wait_on_page_writeback(&folio->page, DATA, false, true);
 
-	if (len == PAGE_SIZE || PageUptodate(page))
+	if (len == folio_size(folio) || folio_test_uptodate(folio))
 		return 0;
 
 	if (!(pos & (PAGE_SIZE - 1)) && (pos + len) >= i_size_read(inode) &&
 	    !f2fs_verity_in_progress(inode)) {
-		zero_user_segment(page, len, PAGE_SIZE);
+		folio_zero_segment(folio, len, PAGE_SIZE);
 		return 0;
 	}
 
 	if (blkaddr == NEW_ADDR) {
-		zero_user_segment(page, 0, PAGE_SIZE);
-		SetPageUptodate(page);
+		folio_zero_segment(folio, 0, folio_size(folio));
+		folio_mark_uptodate(folio);
 	} else {
 		if (!f2fs_is_valid_blkaddr(sbi, blkaddr,
 				DATA_GENERIC_ENHANCE_READ)) {
 			err = -EFSCORRUPTED;
-			goto fail;
+			goto put_folio;
 		}
 		err = f2fs_submit_page_read(use_cow ?
-				F2FS_I(inode)->cow_inode : inode, page,
+				F2FS_I(inode)->cow_inode : inode, &folio->page,
 				blkaddr, 0, true);
 		if (err)
-			goto fail;
+			goto put_folio;
 
-		lock_page(page);
-		if (unlikely(page->mapping != mapping)) {
-			f2fs_put_page(page, 1);
+		folio_lock(folio);
+		if (unlikely(folio->mapping != mapping)) {
+			folio_unlock(folio);
+			folio_put(folio);
 			goto repeat;
 		}
-		if (unlikely(!PageUptodate(page))) {
+		if (unlikely(!folio_test_uptodate(folio))) {
 			err = -EIO;
-			goto fail;
+			goto put_folio;
 		}
 	}
 	return 0;
 
+put_folio:
+	folio_unlock(folio);
+	folio_put(folio);
 fail:
-	f2fs_put_page(page, 1);
 	f2fs_write_failed(inode, pos + len);
 	return err;
 }
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 12/23] fuse: Convert fuse_write_end() to use a folio
  2024-07-17 15:46 [PATCH 00/23] Convert write_begin / write_end to take a folio Matthew Wilcox (Oracle)
                   ` (10 preceding siblings ...)
  2024-07-17 15:47 ` [PATCH 11/23] f2fs: Convert f2fs_write_begin() " Matthew Wilcox (Oracle)
@ 2024-07-17 15:47 ` Matthew Wilcox (Oracle)
  2024-07-17 15:47 ` [PATCH 13/23] fuse: Convert fuse_write_begin() " Matthew Wilcox (Oracle)
                   ` (12 subsequent siblings)
  24 siblings, 0 replies; 31+ messages in thread
From: Matthew Wilcox (Oracle) @ 2024-07-17 15:47 UTC (permalink / raw)
  To: linux-fsdevel; +Cc: Matthew Wilcox (Oracle)

Convert the passed page to a folio and operate on that.
Replaces five calls to compound_head() with one.

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
 fs/fuse/file.c | 15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index f39456c65ed7..f4102c6657af 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -2434,29 +2434,30 @@ static int fuse_write_end(struct file *file, struct address_space *mapping,
 		loff_t pos, unsigned len, unsigned copied,
 		struct page *page, void *fsdata)
 {
-	struct inode *inode = page->mapping->host;
+	struct folio *folio = page_folio(page);
+	struct inode *inode = folio->mapping->host;
 
 	/* Haven't copied anything?  Skip zeroing, size extending, dirtying. */
 	if (!copied)
 		goto unlock;
 
 	pos += copied;
-	if (!PageUptodate(page)) {
+	if (!folio_test_uptodate(folio)) {
 		/* Zero any unwritten bytes at the end of the page */
 		size_t endoff = pos & ~PAGE_MASK;
 		if (endoff)
-			zero_user_segment(page, endoff, PAGE_SIZE);
-		SetPageUptodate(page);
+			folio_zero_segment(folio, endoff, PAGE_SIZE);
+		folio_mark_uptodate(folio);
 	}
 
 	if (pos > inode->i_size)
 		i_size_write(inode, pos);
 
-	set_page_dirty(page);
+	folio_mark_dirty(folio);
 
 unlock:
-	unlock_page(page);
-	put_page(page);
+	folio_unlock(folio);
+	folio_put(folio);
 
 	return copied;
 }
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 13/23] fuse: Convert fuse_write_begin() to use a folio
  2024-07-17 15:46 [PATCH 00/23] Convert write_begin / write_end to take a folio Matthew Wilcox (Oracle)
                   ` (11 preceding siblings ...)
  2024-07-17 15:47 ` [PATCH 12/23] fuse: Convert fuse_write_end() " Matthew Wilcox (Oracle)
@ 2024-07-17 15:47 ` Matthew Wilcox (Oracle)
  2024-07-17 15:47 ` [PATCH 14/23] hostfs: Convert hostfs_write_end() " Matthew Wilcox (Oracle)
                   ` (11 subsequent siblings)
  24 siblings, 0 replies; 31+ messages in thread
From: Matthew Wilcox (Oracle) @ 2024-07-17 15:47 UTC (permalink / raw)
  To: linux-fsdevel; +Cc: Matthew Wilcox (Oracle)

Fetch a folio from the page cache instead of a page and use it throughout
removing several calls to compound_head() and supporting large folios
(in this function).  We still have to convert back to a page for calling
internal fuse functions, but hopefully they will be converted soon.

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
 fs/fuse/file.c | 29 +++++++++++++++--------------
 1 file changed, 15 insertions(+), 14 deletions(-)

diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index f4102c6657af..137485999d3d 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -2391,41 +2391,42 @@ static int fuse_write_begin(struct file *file, struct address_space *mapping,
 {
 	pgoff_t index = pos >> PAGE_SHIFT;
 	struct fuse_conn *fc = get_fuse_conn(file_inode(file));
-	struct page *page;
+	struct folio *folio;
 	loff_t fsize;
 	int err = -ENOMEM;
 
 	WARN_ON(!fc->writeback_cache);
 
-	page = grab_cache_page_write_begin(mapping, index);
-	if (!page)
+	folio = __filemap_get_folio(mapping, index, FGP_WRITEBEGIN,
+			mapping_gfp_mask(mapping));
+	if (IS_ERR(folio))
 		goto error;
 
-	fuse_wait_on_page_writeback(mapping->host, page->index);
+	fuse_wait_on_page_writeback(mapping->host, folio->index);
 
-	if (PageUptodate(page) || len == PAGE_SIZE)
+	if (folio_test_uptodate(folio) || len >= folio_size(folio))
 		goto success;
 	/*
-	 * Check if the start this page comes after the end of file, in which
-	 * case the readpage can be optimized away.
+	 * Check if the start of this folio comes after the end of file,
+	 * in which case the readpage can be optimized away.
 	 */
 	fsize = i_size_read(mapping->host);
-	if (fsize <= (pos & PAGE_MASK)) {
-		size_t off = pos & ~PAGE_MASK;
+	if (fsize <= folio_pos(folio)) {
+		size_t off = offset_in_folio(folio, pos);
 		if (off)
-			zero_user_segment(page, 0, off);
+			folio_zero_segment(folio, 0, off);
 		goto success;
 	}
-	err = fuse_do_readpage(file, page);
+	err = fuse_do_readpage(file, &folio->page);
 	if (err)
 		goto cleanup;
 success:
-	*pagep = page;
+	*pagep = &folio->page;
 	return 0;
 
 cleanup:
-	unlock_page(page);
-	put_page(page);
+	folio_unlock(folio);
+	folio_put(folio);
 error:
 	return err;
 }
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 14/23] hostfs: Convert hostfs_write_end() to use a folio
  2024-07-17 15:46 [PATCH 00/23] Convert write_begin / write_end to take a folio Matthew Wilcox (Oracle)
                   ` (12 preceding siblings ...)
  2024-07-17 15:47 ` [PATCH 13/23] fuse: Convert fuse_write_begin() " Matthew Wilcox (Oracle)
@ 2024-07-17 15:47 ` Matthew Wilcox (Oracle)
  2024-07-17 15:47 ` [PATCH 15/23] jffs2: Convert jffs2_write_end() " Matthew Wilcox (Oracle)
                   ` (10 subsequent siblings)
  24 siblings, 0 replies; 31+ messages in thread
From: Matthew Wilcox (Oracle) @ 2024-07-17 15:47 UTC (permalink / raw)
  To: linux-fsdevel; +Cc: Matthew Wilcox (Oracle)

Convert the passed page to a folio and operate on that.
Replaces four calls to compound_head() with one.

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
 fs/hostfs/hostfs_kern.c | 15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
index 8bf2dc1f9c01..42b70780282d 100644
--- a/fs/hostfs/hostfs_kern.c
+++ b/fs/hostfs/hostfs_kern.c
@@ -478,17 +478,18 @@ static int hostfs_write_end(struct file *file, struct address_space *mapping,
 			    loff_t pos, unsigned len, unsigned copied,
 			    struct page *page, void *fsdata)
 {
+	struct folio *folio = page_folio(page);
 	struct inode *inode = mapping->host;
 	void *buffer;
-	unsigned from = pos & (PAGE_SIZE - 1);
+	size_t from = offset_in_folio(folio, pos);
 	int err;
 
-	buffer = kmap_local_page(page);
-	err = write_file(FILE_HOSTFS_I(file)->fd, &pos, buffer + from, copied);
+	buffer = kmap_local_folio(folio, from);
+	err = write_file(FILE_HOSTFS_I(file)->fd, &pos, buffer, copied);
 	kunmap_local(buffer);
 
-	if (!PageUptodate(page) && err == PAGE_SIZE)
-		SetPageUptodate(page);
+	if (!folio_test_uptodate(folio) && err == folio_size(folio))
+		folio_mark_uptodate(folio);
 
 	/*
 	 * If err > 0, write_file has added err to pos, so we are comparing
@@ -496,8 +497,8 @@ static int hostfs_write_end(struct file *file, struct address_space *mapping,
 	 */
 	if (err > 0 && (pos > inode->i_size))
 		inode->i_size = pos;
-	unlock_page(page);
-	put_page(page);
+	folio_unlock(folio);
+	folio_put(folio);
 
 	return err;
 }
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 15/23] jffs2: Convert jffs2_write_end() to use a folio
  2024-07-17 15:46 [PATCH 00/23] Convert write_begin / write_end to take a folio Matthew Wilcox (Oracle)
                   ` (13 preceding siblings ...)
  2024-07-17 15:47 ` [PATCH 14/23] hostfs: Convert hostfs_write_end() " Matthew Wilcox (Oracle)
@ 2024-07-17 15:47 ` Matthew Wilcox (Oracle)
  2024-07-17 15:47 ` [PATCH 16/23] jffs2: Convert jffs2_write_begin() " Matthew Wilcox (Oracle)
                   ` (9 subsequent siblings)
  24 siblings, 0 replies; 31+ messages in thread
From: Matthew Wilcox (Oracle) @ 2024-07-17 15:47 UTC (permalink / raw)
  To: linux-fsdevel; +Cc: Matthew Wilcox (Oracle)

Convert the passed page to a folio and operate on that.
Replaces six calls to compound_head() with one.
Also use kmap_local instead of kmap.

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
 fs/jffs2/file.c | 34 ++++++++++++++++------------------
 1 file changed, 16 insertions(+), 18 deletions(-)

diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c
index e12cb145147e..1a7dbf846c7c 100644
--- a/fs/jffs2/file.c
+++ b/fs/jffs2/file.c
@@ -240,6 +240,7 @@ static int jffs2_write_end(struct file *filp, struct address_space *mapping,
 			loff_t pos, unsigned len, unsigned copied,
 			struct page *pg, void *fsdata)
 {
+	struct folio *folio = page_folio(pg);
 	/* Actually commit the write from the page cache page we're looking at.
 	 * For now, we write the full page out each time. It sucks, but it's simple
 	 */
@@ -252,16 +253,17 @@ static int jffs2_write_end(struct file *filp, struct address_space *mapping,
 	unsigned aligned_start = start & ~3;
 	int ret = 0;
 	uint32_t writtenlen = 0;
+	void *buf;
 
-	jffs2_dbg(1, "%s(): ino #%lu, page at 0x%lx, range %d-%d, flags %lx\n",
-		  __func__, inode->i_ino, pg->index << PAGE_SHIFT,
-		  start, end, pg->flags);
+	jffs2_dbg(1, "%s(): ino #%lu, page at 0x%llx, range %d-%d, flags %lx\n",
+		  __func__, inode->i_ino, folio_pos(folio),
+		  start, end, folio->flags);
 
 	/* We need to avoid deadlock with page_cache_read() in
-	   jffs2_garbage_collect_pass(). So the page must be
+	   jffs2_garbage_collect_pass(). So the folio must be
 	   up to date to prevent page_cache_read() from trying
 	   to re-lock it. */
-	BUG_ON(!PageUptodate(pg));
+	BUG_ON(!folio_test_uptodate(folio));
 
 	if (end == PAGE_SIZE) {
 		/* When writing out the end of a page, write out the
@@ -276,8 +278,8 @@ static int jffs2_write_end(struct file *filp, struct address_space *mapping,
 	if (!ri) {
 		jffs2_dbg(1, "%s(): Allocation of raw inode failed\n",
 			  __func__);
-		unlock_page(pg);
-		put_page(pg);
+		folio_unlock(folio);
+		folio_put(folio);
 		return -ENOMEM;
 	}
 
@@ -289,15 +291,11 @@ static int jffs2_write_end(struct file *filp, struct address_space *mapping,
 	ri->isize = cpu_to_je32((uint32_t)inode->i_size);
 	ri->atime = ri->ctime = ri->mtime = cpu_to_je32(JFFS2_NOW());
 
-	/* In 2.4, it was already kmapped by generic_file_write(). Doesn't
-	   hurt to do it again. The alternative is ifdefs, which are ugly. */
-	kmap(pg);
-
-	ret = jffs2_write_inode_range(c, f, ri, page_address(pg) + aligned_start,
-				      (pg->index << PAGE_SHIFT) + aligned_start,
+	buf = kmap_local_folio(folio, aligned_start);
+	ret = jffs2_write_inode_range(c, f, ri, buf,
+				      folio_pos(folio) + aligned_start,
 				      end - aligned_start, &writtenlen);
-
-	kunmap(pg);
+	kunmap_local(buf);
 
 	if (ret)
 		mapping_set_error(mapping, ret);
@@ -323,12 +321,12 @@ static int jffs2_write_end(struct file *filp, struct address_space *mapping,
 		   it gets reread */
 		jffs2_dbg(1, "%s(): Not all bytes written. Marking page !uptodate\n",
 			__func__);
-		ClearPageUptodate(pg);
+		folio_clear_uptodate(folio);
 	}
 
 	jffs2_dbg(1, "%s() returning %d\n",
 		  __func__, writtenlen > 0 ? writtenlen : ret);
-	unlock_page(pg);
-	put_page(pg);
+	folio_unlock(folio);
+	folio_put(folio);
 	return writtenlen > 0 ? writtenlen : ret;
 }
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 16/23] jffs2: Convert jffs2_write_begin() to use a folio
  2024-07-17 15:46 [PATCH 00/23] Convert write_begin / write_end to take a folio Matthew Wilcox (Oracle)
                   ` (14 preceding siblings ...)
  2024-07-17 15:47 ` [PATCH 15/23] jffs2: Convert jffs2_write_end() " Matthew Wilcox (Oracle)
@ 2024-07-17 15:47 ` Matthew Wilcox (Oracle)
  2024-07-17 15:47 ` [PATCH 17/23] orangefs: Convert orangefs_write_end() " Matthew Wilcox (Oracle)
                   ` (8 subsequent siblings)
  24 siblings, 0 replies; 31+ messages in thread
From: Matthew Wilcox (Oracle) @ 2024-07-17 15:47 UTC (permalink / raw)
  To: linux-fsdevel; +Cc: Matthew Wilcox (Oracle)

Fetch a folio from the page cache instead of a page and use it throughout
removing several calls to compound_head().  We still have to convert
back to a page for calling internal jffs2 functions, but hopefully they
will be converted soon.

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
 fs/jffs2/file.c | 25 +++++++++++++------------
 1 file changed, 13 insertions(+), 12 deletions(-)

diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c
index 1a7dbf846c7c..ee8f7f029b45 100644
--- a/fs/jffs2/file.c
+++ b/fs/jffs2/file.c
@@ -127,7 +127,7 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
 			loff_t pos, unsigned len,
 			struct page **pagep, void **fsdata)
 {
-	struct page *pg;
+	struct folio *folio;
 	struct inode *inode = mapping->host;
 	struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
 	struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
@@ -206,29 +206,30 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
 	 * page in read_cache_page(), which causes a deadlock.
 	 */
 	mutex_lock(&c->alloc_sem);
-	pg = grab_cache_page_write_begin(mapping, index);
-	if (!pg) {
-		ret = -ENOMEM;
+	folio = __filemap_get_folio(mapping, index, FGP_WRITEBEGIN,
+			mapping_gfp_mask(mapping));
+	if (IS_ERR(folio)) {
+		ret = PTR_ERR(folio);
 		goto release_sem;
 	}
-	*pagep = pg;
+	*pagep = &folio->page;
 
 	/*
-	 * Read in the page if it wasn't already present. Cannot optimize away
-	 * the whole page write case until jffs2_write_end can handle the
+	 * Read in the folio if it wasn't already present. Cannot optimize away
+	 * the whole folio write case until jffs2_write_end can handle the
 	 * case of a short-copy.
 	 */
-	if (!PageUptodate(pg)) {
+	if (!folio_test_uptodate(folio)) {
 		mutex_lock(&f->sem);
-		ret = jffs2_do_readpage_nolock(inode, pg);
+		ret = jffs2_do_readpage_nolock(inode, &folio->page);
 		mutex_unlock(&f->sem);
 		if (ret) {
-			unlock_page(pg);
-			put_page(pg);
+			folio_unlock(folio);
+			folio_put(folio);
 			goto release_sem;
 		}
 	}
-	jffs2_dbg(1, "end write_begin(). pg->flags %lx\n", pg->flags);
+	jffs2_dbg(1, "end write_begin(). folio->flags %lx\n", folio->flags);
 
 release_sem:
 	mutex_unlock(&c->alloc_sem);
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 17/23] orangefs: Convert orangefs_write_end() to use a folio
  2024-07-17 15:46 [PATCH 00/23] Convert write_begin / write_end to take a folio Matthew Wilcox (Oracle)
                   ` (15 preceding siblings ...)
  2024-07-17 15:47 ` [PATCH 16/23] jffs2: Convert jffs2_write_begin() " Matthew Wilcox (Oracle)
@ 2024-07-17 15:47 ` Matthew Wilcox (Oracle)
  2024-07-17 15:47 ` [PATCH 18/23] orangefs: Convert orangefs_write_begin() " Matthew Wilcox (Oracle)
                   ` (7 subsequent siblings)
  24 siblings, 0 replies; 31+ messages in thread
From: Matthew Wilcox (Oracle) @ 2024-07-17 15:47 UTC (permalink / raw)
  To: linux-fsdevel; +Cc: Matthew Wilcox (Oracle)

Convert the passed page to a folio and operate on that.
Replaces five calls to compound_head() with one.

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
 fs/orangefs/inode.c | 21 +++++++++++----------
 1 file changed, 11 insertions(+), 10 deletions(-)

diff --git a/fs/orangefs/inode.c b/fs/orangefs/inode.c
index fdb9b65db1de..6595417f62b1 100644
--- a/fs/orangefs/inode.c
+++ b/fs/orangefs/inode.c
@@ -367,7 +367,8 @@ static int orangefs_write_begin(struct file *file,
 static int orangefs_write_end(struct file *file, struct address_space *mapping,
     loff_t pos, unsigned len, unsigned copied, struct page *page, void *fsdata)
 {
-	struct inode *inode = page->mapping->host;
+	struct folio *folio = page_folio(page);
+	struct inode *inode = folio->mapping->host;
 	loff_t last_pos = pos + copied;
 
 	/*
@@ -377,23 +378,23 @@ static int orangefs_write_end(struct file *file, struct address_space *mapping,
 	if (last_pos > inode->i_size)
 		i_size_write(inode, last_pos);
 
-	/* zero the stale part of the page if we did a short copy */
-	if (!PageUptodate(page)) {
+	/* zero the stale part of the folio if we did a short copy */
+	if (!folio_test_uptodate(folio)) {
 		unsigned from = pos & (PAGE_SIZE - 1);
 		if (copied < len) {
-			zero_user(page, from + copied, len - copied);
+			folio_zero_range(folio, from + copied, len - copied);
 		}
 		/* Set fully written pages uptodate. */
-		if (pos == page_offset(page) &&
+		if (pos == folio_pos(folio) &&
 		    (len == PAGE_SIZE || pos + len == inode->i_size)) {
-			zero_user_segment(page, from + copied, PAGE_SIZE);
-			SetPageUptodate(page);
+			folio_zero_segment(folio, from + copied, PAGE_SIZE);
+			folio_mark_uptodate(folio);
 		}
 	}
 
-	set_page_dirty(page);
-	unlock_page(page);
-	put_page(page);
+	folio_mark_dirty(folio);
+	folio_unlock(folio);
+	folio_put(folio);
 
 	mark_inode_dirty_sync(file_inode(file));
 	return copied;
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 18/23] orangefs: Convert orangefs_write_begin() to use a folio
  2024-07-17 15:46 [PATCH 00/23] Convert write_begin / write_end to take a folio Matthew Wilcox (Oracle)
                   ` (16 preceding siblings ...)
  2024-07-17 15:47 ` [PATCH 17/23] orangefs: Convert orangefs_write_end() " Matthew Wilcox (Oracle)
@ 2024-07-17 15:47 ` Matthew Wilcox (Oracle)
  2024-07-17 15:47 ` [PATCH 19/23] vboxsf: Use a folio in vboxsf_write_end() Matthew Wilcox (Oracle)
                   ` (6 subsequent siblings)
  24 siblings, 0 replies; 31+ messages in thread
From: Matthew Wilcox (Oracle) @ 2024-07-17 15:47 UTC (permalink / raw)
  To: linux-fsdevel; +Cc: Matthew Wilcox (Oracle)

Retrieve a folio from the page cache instead of a page.  This
function was previously mostly converted to use a folio, so it's
a fairly small change.

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
 fs/orangefs/inode.c | 14 +++++---------
 1 file changed, 5 insertions(+), 9 deletions(-)

diff --git a/fs/orangefs/inode.c b/fs/orangefs/inode.c
index 6595417f62b1..e8440fa7d73c 100644
--- a/fs/orangefs/inode.c
+++ b/fs/orangefs/inode.c
@@ -313,18 +313,14 @@ static int orangefs_write_begin(struct file *file,
 {
 	struct orangefs_write_range *wr;
 	struct folio *folio;
-	struct page *page;
-	pgoff_t index;
 	int ret;
 
-	index = pos >> PAGE_SHIFT;
+	folio = __filemap_get_folio(mapping, pos / PAGE_SIZE, FGP_WRITEBEGIN,
+			mapping_gfp_mask(mapping));
+	if (IS_ERR(folio))
+		return PTR_ERR(folio);
 
-	page = grab_cache_page_write_begin(mapping, index);
-	if (!page)
-		return -ENOMEM;
-
-	*pagep = page;
-	folio = page_folio(page);
+	*pagep = &folio->page;
 
 	if (folio_test_dirty(folio) && !folio_test_private(folio)) {
 		/*
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 19/23] vboxsf: Use a folio in vboxsf_write_end()
  2024-07-17 15:46 [PATCH 00/23] Convert write_begin / write_end to take a folio Matthew Wilcox (Oracle)
                   ` (17 preceding siblings ...)
  2024-07-17 15:47 ` [PATCH 18/23] orangefs: Convert orangefs_write_begin() " Matthew Wilcox (Oracle)
@ 2024-07-17 15:47 ` Matthew Wilcox (Oracle)
  2024-07-17 15:47 ` [PATCH 20/23] fs: Convert aops->write_end to take a folio Matthew Wilcox (Oracle)
                   ` (5 subsequent siblings)
  24 siblings, 0 replies; 31+ messages in thread
From: Matthew Wilcox (Oracle) @ 2024-07-17 15:47 UTC (permalink / raw)
  To: linux-fsdevel; +Cc: Matthew Wilcox (Oracle)

Because we have to kmap() the page before calling vboxsf_write(), we
can't entirely remove the use of struct page.  But we can eliminate some
uses of old APIs and remove some unnecessary calls to compound_head().

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
 fs/vboxsf/file.c | 19 ++++++++++---------
 1 file changed, 10 insertions(+), 9 deletions(-)

diff --git a/fs/vboxsf/file.c b/fs/vboxsf/file.c
index fdb4da24d662..029f106d56d9 100644
--- a/fs/vboxsf/file.c
+++ b/fs/vboxsf/file.c
@@ -302,16 +302,17 @@ static int vboxsf_write_end(struct file *file, struct address_space *mapping,
 			    loff_t pos, unsigned int len, unsigned int copied,
 			    struct page *page, void *fsdata)
 {
+	struct folio *folio = page_folio(page);
 	struct inode *inode = mapping->host;
 	struct vboxsf_handle *sf_handle = file->private_data;
-	unsigned int from = pos & ~PAGE_MASK;
+	size_t from = offset_in_folio(folio, pos);
 	u32 nwritten = len;
 	u8 *buf;
 	int err;
 
-	/* zero the stale part of the page if we did a short copy */
-	if (!PageUptodate(page) && copied < len)
-		zero_user(page, from + copied, len - copied);
+	/* zero the stale part of the folio if we did a short copy */
+	if (!folio_test_uptodate(folio) && copied < len)
+		folio_zero_range(folio, from + copied, len - copied);
 
 	buf = kmap(page);
 	err = vboxsf_write(sf_handle->root, sf_handle->handle,
@@ -326,16 +327,16 @@ static int vboxsf_write_end(struct file *file, struct address_space *mapping,
 	/* mtime changed */
 	VBOXSF_I(inode)->force_restat = 1;
 
-	if (!PageUptodate(page) && nwritten == PAGE_SIZE)
-		SetPageUptodate(page);
+	if (!folio_test_uptodate(folio) && nwritten == folio_size(folio))
+		folio_mark_uptodate(folio);
 
 	pos += nwritten;
 	if (pos > inode->i_size)
 		i_size_write(inode, pos);
 
 out:
-	unlock_page(page);
-	put_page(page);
+	folio_unlock(folio);
+	folio_put(folio);
 
 	return nwritten;
 }
@@ -343,7 +344,7 @@ static int vboxsf_write_end(struct file *file, struct address_space *mapping,
 /*
  * Note simple_write_begin does not read the page from disk on partial writes
  * this is ok since vboxsf_write_end only writes the written parts of the
- * page and it does not call SetPageUptodate for partial writes.
+ * page and it does not call folio_mark_uptodate for partial writes.
  */
 const struct address_space_operations vboxsf_reg_aops = {
 	.read_folio = vboxsf_read_folio,
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 20/23] fs: Convert aops->write_end to take a folio
  2024-07-17 15:46 [PATCH 00/23] Convert write_begin / write_end to take a folio Matthew Wilcox (Oracle)
                   ` (18 preceding siblings ...)
  2024-07-17 15:47 ` [PATCH 19/23] vboxsf: Use a folio in vboxsf_write_end() Matthew Wilcox (Oracle)
@ 2024-07-17 15:47 ` Matthew Wilcox (Oracle)
  2024-07-17 15:47 ` [PATCH 21/23] fs: Convert aops->write_begin " Matthew Wilcox (Oracle)
                   ` (4 subsequent siblings)
  24 siblings, 0 replies; 31+ messages in thread
From: Matthew Wilcox (Oracle) @ 2024-07-17 15:47 UTC (permalink / raw)
  To: linux-fsdevel; +Cc: Matthew Wilcox (Oracle)

Most callers have a folio, and most implementations operate on a folio,
so remove the conversion from folio->page->folio to fit through this
interface.

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
 Documentation/filesystems/locking.rst     |  2 +-
 Documentation/filesystems/vfs.rst         |  6 +++---
 block/fops.c                              |  3 +--
 drivers/gpu/drm/i915/gem/i915_gem_shmem.c |  4 ++--
 fs/affs/file.c                            |  9 ++++-----
 fs/bcachefs/fs-io-buffered.c              |  3 +--
 fs/bcachefs/fs-io-buffered.h              |  2 +-
 fs/buffer.c                               |  9 ++++-----
 fs/ceph/addr.c                            |  3 +--
 fs/ecryptfs/mmap.c                        |  5 ++---
 fs/exfat/file.c                           |  2 +-
 fs/exfat/inode.c                          |  4 ++--
 fs/ext2/inode.c                           |  4 ++--
 fs/ext4/inode.c                           | 11 ++++-------
 fs/ext4/verity.c                          |  2 +-
 fs/f2fs/data.c                            |  3 +--
 fs/f2fs/super.c                           |  2 +-
 fs/f2fs/verity.c                          |  2 +-
 fs/fat/inode.c                            |  4 ++--
 fs/fuse/file.c                            |  3 +--
 fs/hfs/extent.c                           |  2 +-
 fs/hfsplus/extents.c                      |  2 +-
 fs/hostfs/hostfs_kern.c                   |  3 +--
 fs/hpfs/file.c                            |  4 ++--
 fs/hugetlbfs/inode.c                      |  2 +-
 fs/jffs2/file.c                           |  5 ++---
 fs/jfs/inode.c                            |  4 ++--
 fs/libfs.c                                |  9 ++++-----
 fs/namei.c                                |  2 +-
 fs/nfs/file.c                             |  3 +--
 fs/nilfs2/inode.c                         |  6 +++---
 fs/ntfs3/file.c                           |  2 +-
 fs/ntfs3/inode.c                          |  5 ++---
 fs/ntfs3/ntfs_fs.h                        |  2 +-
 fs/ocfs2/aops.c                           |  2 +-
 fs/orangefs/inode.c                       |  4 ++--
 fs/reiserfs/inode.c                       | 11 +++++------
 fs/ubifs/file.c                           |  3 +--
 fs/udf/inode.c                            |  6 ++----
 fs/ufs/inode.c                            |  4 ++--
 fs/vboxsf/file.c                          |  7 +++----
 include/linux/buffer_head.h               |  4 ++--
 include/linux/fs.h                        |  2 +-
 mm/filemap.c                              |  2 +-
 mm/shmem.c                                |  3 +--
 45 files changed, 80 insertions(+), 102 deletions(-)

diff --git a/Documentation/filesystems/locking.rst b/Documentation/filesystems/locking.rst
index e664061ed55d..827fb5a073b7 100644
--- a/Documentation/filesystems/locking.rst
+++ b/Documentation/filesystems/locking.rst
@@ -254,7 +254,7 @@ prototypes::
 				struct page **pagep, void **fsdata);
 	int (*write_end)(struct file *, struct address_space *mapping,
 				loff_t pos, unsigned len, unsigned copied,
-				struct page *page, void *fsdata);
+				struct folio *folio, void *fsdata);
 	sector_t (*bmap)(struct address_space *, sector_t);
 	void (*invalidate_folio) (struct folio *, size_t start, size_t len);
 	bool (*release_folio)(struct folio *, gfp_t);
diff --git a/Documentation/filesystems/vfs.rst b/Documentation/filesystems/vfs.rst
index 6e903a903f8f..0e24f770c568 100644
--- a/Documentation/filesystems/vfs.rst
+++ b/Documentation/filesystems/vfs.rst
@@ -810,7 +810,7 @@ cache in your filesystem.  The following members are defined:
 				struct page **pagep, void **fsdata);
 		int (*write_end)(struct file *, struct address_space *mapping,
 				 loff_t pos, unsigned len, unsigned copied,
-				 struct page *page, void *fsdata);
+				 struct folio *folio, void *fsdata);
 		sector_t (*bmap)(struct address_space *, sector_t);
 		void (*invalidate_folio) (struct folio *, size_t start, size_t len);
 		bool (*release_folio)(struct folio *, gfp_t);
@@ -944,8 +944,8 @@ cache in your filesystem.  The following members are defined:
 	called.  len is the original len passed to write_begin, and
 	copied is the amount that was able to be copied.
 
-	The filesystem must take care of unlocking the page and
-	releasing it refcount, and updating i_size.
+	The filesystem must take care of unlocking the folio,
+	decrementing its refcount, and updating i_size.
 
 	Returns < 0 on failure, otherwise the number of bytes (<=
 	'copied') that were able to be copied into pagecache.
diff --git a/block/fops.c b/block/fops.c
index df0e762cf397..cd96a6f17119 100644
--- a/block/fops.c
+++ b/block/fops.c
@@ -457,10 +457,9 @@ static int blkdev_write_begin(struct file *file, struct address_space *mapping,
 }
 
 static int blkdev_write_end(struct file *file, struct address_space *mapping,
-		loff_t pos, unsigned len, unsigned copied, struct page *page,
+		loff_t pos, unsigned len, unsigned copied, struct folio *folio,
 		void *fsdata)
 {
-	struct folio *folio = page_folio(page);
 	int ret;
 	ret = block_write_end(file, mapping, pos, len, copied, folio, fsdata);
 
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_shmem.c b/drivers/gpu/drm/i915/gem/i915_gem_shmem.c
index c5e1c718a6d2..3513165a2964 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_shmem.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_shmem.c
@@ -494,7 +494,7 @@ shmem_pwrite(struct drm_i915_gem_object *obj,
 		kunmap_local(vaddr);
 
 		err = aops->write_end(obj->base.filp, mapping, offset, len,
-				      len - unwritten, page, data);
+				      len - unwritten, page_folio(page), data);
 		if (err < 0)
 			return err;
 
@@ -688,7 +688,7 @@ i915_gem_object_create_shmem_from_data(struct drm_i915_private *i915,
 		kunmap(page);
 
 		err = aops->write_end(file, file->f_mapping, offset, len, len,
-				      page, pgdata);
+				      page_folio(page), pgdata);
 		if (err < 0)
 			goto fail;
 
diff --git a/fs/affs/file.c b/fs/affs/file.c
index 04c018e19602..6a6c5bc41b8f 100644
--- a/fs/affs/file.c
+++ b/fs/affs/file.c
@@ -433,12 +433,12 @@ static int affs_write_begin(struct file *file, struct address_space *mapping,
 
 static int affs_write_end(struct file *file, struct address_space *mapping,
 			  loff_t pos, unsigned int len, unsigned int copied,
-			  struct page *page, void *fsdata)
+			  struct folio *folio, void *fsdata)
 {
 	struct inode *inode = mapping->host;
 	int ret;
 
-	ret = generic_write_end(file, mapping, pos, len, copied, page, fsdata);
+	ret = generic_write_end(file, mapping, pos, len, copied, folio, fsdata);
 
 	/* Clear Archived bit on file writes, as AmigaOS would do */
 	if (AFFS_I(inode)->i_protect & FIBF_ARCHIVED) {
@@ -687,9 +687,8 @@ static int affs_write_begin_ofs(struct file *file, struct address_space *mapping
 
 static int affs_write_end_ofs(struct file *file, struct address_space *mapping,
 				loff_t pos, unsigned len, unsigned copied,
-				struct page *page, void *fsdata)
+				struct folio *folio, void *fsdata)
 {
-	struct folio *folio = page_folio(page);
 	struct inode *inode = mapping->host;
 	struct super_block *sb = inode->i_sb;
 	struct buffer_head *bh, *prev_bh;
@@ -889,7 +888,7 @@ affs_truncate(struct inode *inode)
 
 		res = mapping->a_ops->write_begin(NULL, mapping, isize, 0, &page, &fsdata);
 		if (!res)
-			res = mapping->a_ops->write_end(NULL, mapping, isize, 0, 0, page, fsdata);
+			res = mapping->a_ops->write_end(NULL, mapping, isize, 0, 0, page_folio(page), fsdata);
 		else
 			inode->i_size = AFFS_I(inode)->mmu_private;
 		mark_inode_dirty(inode);
diff --git a/fs/bcachefs/fs-io-buffered.c b/fs/bcachefs/fs-io-buffered.c
index cc33d763f722..46ae9ef3589a 100644
--- a/fs/bcachefs/fs-io-buffered.c
+++ b/fs/bcachefs/fs-io-buffered.c
@@ -743,12 +743,11 @@ int bch2_write_begin(struct file *file, struct address_space *mapping,
 
 int bch2_write_end(struct file *file, struct address_space *mapping,
 		   loff_t pos, unsigned len, unsigned copied,
-		   struct page *page, void *fsdata)
+		   struct folio *folio, void *fsdata)
 {
 	struct bch_inode_info *inode = to_bch_ei(mapping->host);
 	struct bch_fs *c = inode->v.i_sb->s_fs_info;
 	struct bch2_folio_reservation *res = fsdata;
-	struct folio *folio = page_folio(page);
 	unsigned offset = pos - folio_pos(folio);
 
 	lockdep_assert_held(&inode->v.i_rwsem);
diff --git a/fs/bcachefs/fs-io-buffered.h b/fs/bcachefs/fs-io-buffered.h
index a6126ff790e6..16569b9874e0 100644
--- a/fs/bcachefs/fs-io-buffered.h
+++ b/fs/bcachefs/fs-io-buffered.h
@@ -13,7 +13,7 @@ void bch2_readahead(struct readahead_control *);
 int bch2_write_begin(struct file *, struct address_space *, loff_t,
 		     unsigned, struct page **, void **);
 int bch2_write_end(struct file *, struct address_space *, loff_t,
-		   unsigned, unsigned, struct page *, void *);
+		   unsigned len, unsigned copied, struct folio *, void *);
 
 ssize_t bch2_write_iter(struct kiocb *, struct iov_iter *);
 
diff --git a/fs/buffer.c b/fs/buffer.c
index acba3dfe55d8..1a0f2f65e890 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -2280,9 +2280,8 @@ EXPORT_SYMBOL(block_write_end);
 
 int generic_write_end(struct file *file, struct address_space *mapping,
 			loff_t pos, unsigned len, unsigned copied,
-			struct page *page, void *fsdata)
+			struct folio *folio, void *fsdata)
 {
-	struct folio *folio = page_folio(page);
 	struct inode *inode = mapping->host;
 	loff_t old_size = inode->i_size;
 	bool i_size_changed = false;
@@ -2480,7 +2479,7 @@ int generic_cont_expand_simple(struct inode *inode, loff_t size)
 	if (err)
 		goto out;
 
-	err = aops->write_end(NULL, mapping, size, 0, 0, page, fsdata);
+	err = aops->write_end(NULL, mapping, size, 0, 0, page_folio(page), fsdata);
 	BUG_ON(err > 0);
 
 out:
@@ -2518,7 +2517,7 @@ static int cont_expand_zero(struct file *file, struct address_space *mapping,
 			goto out;
 		zero_user(page, zerofrom, len);
 		err = aops->write_end(file, mapping, curpos, len, len,
-						page, fsdata);
+						page_folio(page), fsdata);
 		if (err < 0)
 			goto out;
 		BUG_ON(err != len);
@@ -2551,7 +2550,7 @@ static int cont_expand_zero(struct file *file, struct address_space *mapping,
 			goto out;
 		zero_user(page, zerofrom, len);
 		err = aops->write_end(file, mapping, curpos, len, len,
-						page, fsdata);
+						page_folio(page), fsdata);
 		if (err < 0)
 			goto out;
 		BUG_ON(err != len);
diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c
index 8c16bc5250ef..87369e2659c7 100644
--- a/fs/ceph/addr.c
+++ b/fs/ceph/addr.c
@@ -1509,9 +1509,8 @@ static int ceph_write_begin(struct file *file, struct address_space *mapping,
  */
 static int ceph_write_end(struct file *file, struct address_space *mapping,
 			  loff_t pos, unsigned len, unsigned copied,
-			  struct page *subpage, void *fsdata)
+			  struct folio *folio, void *fsdata)
 {
-	struct folio *folio = page_folio(subpage);
 	struct inode *inode = file_inode(file);
 	struct ceph_client *cl = ceph_inode_to_client(inode);
 	bool check_cap = false;
diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c
index 75ce28d757b7..f43e42ede75e 100644
--- a/fs/ecryptfs/mmap.c
+++ b/fs/ecryptfs/mmap.c
@@ -458,15 +458,14 @@ int ecryptfs_write_inode_size_to_metadata(struct inode *ecryptfs_inode)
  * @pos: The file position
  * @len: The length of the data (unused)
  * @copied: The amount of data copied
- * @page: The eCryptfs page
+ * @folio: The eCryptfs folio
  * @fsdata: The fsdata (unused)
  */
 static int ecryptfs_write_end(struct file *file,
 			struct address_space *mapping,
 			loff_t pos, unsigned len, unsigned copied,
-			struct page *page, void *fsdata)
+			struct folio *folio, void *fsdata)
 {
-	struct folio *folio = page_folio(page);
 	pgoff_t index = pos >> PAGE_SHIFT;
 	unsigned from = pos & (PAGE_SIZE - 1);
 	unsigned to = from + copied;
diff --git a/fs/exfat/file.c b/fs/exfat/file.c
index 64c31867bc76..7144472d092e 100644
--- a/fs/exfat/file.c
+++ b/fs/exfat/file.c
@@ -548,7 +548,7 @@ static int exfat_file_zeroed_range(struct file *file, loff_t start, loff_t end)
 
 		zero_user_segment(page, zerofrom, zerofrom + len);
 
-		err = ops->write_end(file, mapping, start, len, len, page, NULL);
+		err = ops->write_end(file, mapping, start, len, len, page_folio(page), NULL);
 		if (err < 0)
 			goto out;
 		start += len;
diff --git a/fs/exfat/inode.c b/fs/exfat/inode.c
index dd894e558c91..871e9e3e407e 100644
--- a/fs/exfat/inode.c
+++ b/fs/exfat/inode.c
@@ -463,13 +463,13 @@ static int exfat_write_begin(struct file *file, struct address_space *mapping,
 
 static int exfat_write_end(struct file *file, struct address_space *mapping,
 		loff_t pos, unsigned int len, unsigned int copied,
-		struct page *pagep, void *fsdata)
+		struct folio *folio, void *fsdata)
 {
 	struct inode *inode = mapping->host;
 	struct exfat_inode_info *ei = EXFAT_I(inode);
 	int err;
 
-	err = generic_write_end(file, mapping, pos, len, copied, pagep, fsdata);
+	err = generic_write_end(file, mapping, pos, len, copied, folio, fsdata);
 
 	if (ei->i_size_aligned < i_size_read(inode)) {
 		exfat_fs_error(inode->i_sb,
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c
index 0caa1650cee8..aba41f6150e5 100644
--- a/fs/ext2/inode.c
+++ b/fs/ext2/inode.c
@@ -928,11 +928,11 @@ ext2_write_begin(struct file *file, struct address_space *mapping,
 
 static int ext2_write_end(struct file *file, struct address_space *mapping,
 			loff_t pos, unsigned len, unsigned copied,
-			struct page *page, void *fsdata)
+			struct folio *folio, void *fsdata)
 {
 	int ret;
 
-	ret = generic_write_end(file, mapping, pos, len, copied, page, fsdata);
+	ret = generic_write_end(file, mapping, pos, len, copied, folio, fsdata);
 	if (ret < len)
 		ext2_write_failed(mapping, pos + len);
 	return ret;
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 1e4831d83adc..e19ac0a82bdc 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -1298,9 +1298,8 @@ static int write_end_fn(handle_t *handle, struct inode *inode,
 static int ext4_write_end(struct file *file,
 			  struct address_space *mapping,
 			  loff_t pos, unsigned len, unsigned copied,
-			  struct page *page, void *fsdata)
+			  struct folio *folio, void *fsdata)
 {
-	struct folio *folio = page_folio(page);
 	handle_t *handle = ext4_journal_current_handle();
 	struct inode *inode = mapping->host;
 	loff_t old_size = inode->i_size;
@@ -1402,9 +1401,8 @@ static void ext4_journalled_zero_new_buffers(handle_t *handle,
 static int ext4_journalled_write_end(struct file *file,
 				     struct address_space *mapping,
 				     loff_t pos, unsigned len, unsigned copied,
-				     struct page *page, void *fsdata)
+				     struct folio *folio, void *fsdata)
 {
-	struct folio *folio = page_folio(page);
 	handle_t *handle = ext4_journal_current_handle();
 	struct inode *inode = mapping->host;
 	loff_t old_size = inode->i_size;
@@ -3080,15 +3078,14 @@ static int ext4_da_do_write_end(struct address_space *mapping,
 static int ext4_da_write_end(struct file *file,
 			     struct address_space *mapping,
 			     loff_t pos, unsigned len, unsigned copied,
-			     struct page *page, void *fsdata)
+			     struct folio *folio, void *fsdata)
 {
 	struct inode *inode = mapping->host;
 	int write_mode = (int)(unsigned long)fsdata;
-	struct folio *folio = page_folio(page);
 
 	if (write_mode == FALL_BACK_TO_NONDELALLOC)
 		return ext4_write_end(file, mapping, pos,
-				      len, copied, &folio->page, fsdata);
+				      len, copied, folio, fsdata);
 
 	trace_ext4_da_write_end(inode, pos, len, copied);
 
diff --git a/fs/ext4/verity.c b/fs/ext4/verity.c
index 2f37e1ea3955..86ef272296ab 100644
--- a/fs/ext4/verity.c
+++ b/fs/ext4/verity.c
@@ -86,7 +86,7 @@ static int pagecache_write(struct inode *inode, const void *buf, size_t count,
 
 		memcpy_to_page(page, offset_in_page(pos), buf, n);
 
-		res = aops->write_end(NULL, mapping, pos, n, n, page, fsdata);
+		res = aops->write_end(NULL, mapping, pos, n, n, page_folio(page), fsdata);
 		if (res < 0)
 			return res;
 		if (res != n)
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 9a45f9fb8a64..4c32e2cfc403 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -3689,9 +3689,8 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping,
 static int f2fs_write_end(struct file *file,
 			struct address_space *mapping,
 			loff_t pos, unsigned len, unsigned copied,
-			struct page *page, void *fsdata)
+			struct folio *folio, void *fsdata)
 {
-	struct folio *folio = page_folio(page);
 	struct inode *inode = folio->mapping->host;
 
 	trace_f2fs_write_end(inode, pos, len, copied);
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index 3959fd137cc9..cfd38cd4f82c 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -2700,7 +2700,7 @@ static ssize_t f2fs_quota_write(struct super_block *sb, int type,
 		memcpy_to_page(page, offset, data, tocopy);
 
 		a_ops->write_end(NULL, mapping, off, tocopy, tocopy,
-						page, fsdata);
+						page_folio(page), fsdata);
 		offset = 0;
 		towrite -= tocopy;
 		off += tocopy;
diff --git a/fs/f2fs/verity.c b/fs/f2fs/verity.c
index f7bb0c54502c..486512144bf1 100644
--- a/fs/f2fs/verity.c
+++ b/fs/f2fs/verity.c
@@ -90,7 +90,7 @@ static int pagecache_write(struct inode *inode, const void *buf, size_t count,
 
 		memcpy_to_page(page, offset_in_page(pos), buf, n);
 
-		res = aops->write_end(NULL, mapping, pos, n, n, page, fsdata);
+		res = aops->write_end(NULL, mapping, pos, n, n, page_folio(page), fsdata);
 		if (res < 0)
 			return res;
 		if (res != n)
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index 19115fd2d2a4..8ed02b17d591 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -236,11 +236,11 @@ static int fat_write_begin(struct file *file, struct address_space *mapping,
 
 static int fat_write_end(struct file *file, struct address_space *mapping,
 			loff_t pos, unsigned len, unsigned copied,
-			struct page *pagep, void *fsdata)
+			struct folio *folio, void *fsdata)
 {
 	struct inode *inode = mapping->host;
 	int err;
-	err = generic_write_end(file, mapping, pos, len, copied, pagep, fsdata);
+	err = generic_write_end(file, mapping, pos, len, copied, folio, fsdata);
 	if (err < len)
 		fat_write_failed(mapping, pos + len);
 	if (!(err < 0) && !(MSDOS_I(inode)->i_attrs & ATTR_ARCH)) {
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 137485999d3d..a5cd6e4f9b2b 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -2433,9 +2433,8 @@ static int fuse_write_begin(struct file *file, struct address_space *mapping,
 
 static int fuse_write_end(struct file *file, struct address_space *mapping,
 		loff_t pos, unsigned len, unsigned copied,
-		struct page *page, void *fsdata)
+		struct folio *folio, void *fsdata)
 {
-	struct folio *folio = page_folio(page);
 	struct inode *inode = folio->mapping->host;
 
 	/* Haven't copied anything?  Skip zeroing, size extending, dirtying. */
diff --git a/fs/hfs/extent.c b/fs/hfs/extent.c
index 6d1878b99b30..30512dbb79f0 100644
--- a/fs/hfs/extent.c
+++ b/fs/hfs/extent.c
@@ -495,7 +495,7 @@ void hfs_file_truncate(struct inode *inode)
 				&fsdata);
 		if (!res) {
 			res = generic_write_end(NULL, mapping, size + 1, 0, 0,
-					page, fsdata);
+					page_folio(page), fsdata);
 		}
 		if (res)
 			inode->i_size = HFS_I(inode)->phys_size;
diff --git a/fs/hfsplus/extents.c b/fs/hfsplus/extents.c
index 9c51867dddc5..776c0ea722cb 100644
--- a/fs/hfsplus/extents.c
+++ b/fs/hfsplus/extents.c
@@ -563,7 +563,7 @@ void hfsplus_file_truncate(struct inode *inode)
 		if (res)
 			return;
 		res = generic_write_end(NULL, mapping, size, 0, 0,
-					page, fsdata);
+					page_folio(page), fsdata);
 		if (res < 0)
 			return;
 		mark_inode_dirty(inode);
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
index 42b70780282d..6452431231ab 100644
--- a/fs/hostfs/hostfs_kern.c
+++ b/fs/hostfs/hostfs_kern.c
@@ -476,9 +476,8 @@ static int hostfs_write_begin(struct file *file, struct address_space *mapping,
 
 static int hostfs_write_end(struct file *file, struct address_space *mapping,
 			    loff_t pos, unsigned len, unsigned copied,
-			    struct page *page, void *fsdata)
+			    struct folio *folio, void *fsdata)
 {
-	struct folio *folio = page_folio(page);
 	struct inode *inode = mapping->host;
 	void *buffer;
 	size_t from = offset_in_folio(folio, pos);
diff --git a/fs/hpfs/file.c b/fs/hpfs/file.c
index 1bb8d97cd9ae..11e2d9e612ac 100644
--- a/fs/hpfs/file.c
+++ b/fs/hpfs/file.c
@@ -206,11 +206,11 @@ static int hpfs_write_begin(struct file *file, struct address_space *mapping,
 
 static int hpfs_write_end(struct file *file, struct address_space *mapping,
 			loff_t pos, unsigned len, unsigned copied,
-			struct page *pagep, void *fsdata)
+			struct folio *folio, void *fsdata)
 {
 	struct inode *inode = mapping->host;
 	int err;
-	err = generic_write_end(file, mapping, pos, len, copied, pagep, fsdata);
+	err = generic_write_end(file, mapping, pos, len, copied, folio, fsdata);
 	if (err < len)
 		hpfs_write_failed(mapping, pos + len);
 	if (!(err < 0)) {
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index 9f6cff356796..b7a30055e6f4 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -395,7 +395,7 @@ static int hugetlbfs_write_begin(struct file *file,
 
 static int hugetlbfs_write_end(struct file *file, struct address_space *mapping,
 			loff_t pos, unsigned len, unsigned copied,
-			struct page *page, void *fsdata)
+			struct folio *folio, void *fsdata)
 {
 	BUG();
 	return -EINVAL;
diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c
index ee8f7f029b45..b6fe1f1e8ea9 100644
--- a/fs/jffs2/file.c
+++ b/fs/jffs2/file.c
@@ -23,7 +23,7 @@
 
 static int jffs2_write_end(struct file *filp, struct address_space *mapping,
 			loff_t pos, unsigned len, unsigned copied,
-			struct page *pg, void *fsdata);
+			struct folio *folio, void *fsdata);
 static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
 			loff_t pos, unsigned len,
 			struct page **pagep, void **fsdata);
@@ -239,9 +239,8 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
 
 static int jffs2_write_end(struct file *filp, struct address_space *mapping,
 			loff_t pos, unsigned len, unsigned copied,
-			struct page *pg, void *fsdata)
+			struct folio *folio, void *fsdata)
 {
-	struct folio *folio = page_folio(pg);
 	/* Actually commit the write from the page cache page we're looking at.
 	 * For now, we write the full page out each time. It sucks, but it's simple
 	 */
diff --git a/fs/jfs/inode.c b/fs/jfs/inode.c
index 1a6b5921d17a..d63494182548 100644
--- a/fs/jfs/inode.c
+++ b/fs/jfs/inode.c
@@ -304,12 +304,12 @@ static int jfs_write_begin(struct file *file, struct address_space *mapping,
 }
 
 static int jfs_write_end(struct file *file, struct address_space *mapping,
-		loff_t pos, unsigned len, unsigned copied, struct page *page,
+		loff_t pos, unsigned len, unsigned copied, struct folio *folio,
 		void *fsdata)
 {
 	int ret;
 
-	ret = generic_write_end(file, mapping, pos, len, copied, page, fsdata);
+	ret = generic_write_end(file, mapping, pos, len, copied, folio, fsdata);
 	if (ret < len)
 		jfs_write_failed(mapping, pos + len);
 	return ret;
diff --git a/fs/libfs.c b/fs/libfs.c
index 8aa34870449f..4581be1d5b32 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -929,11 +929,11 @@ EXPORT_SYMBOL(simple_write_begin);
  * @pos: 		"
  * @len: 		"
  * @copied: 		"
- * @page: 		"
+ * @folio: 		"
  * @fsdata: 		"
  *
- * simple_write_end does the minimum needed for updating a page after writing is
- * done. It has the same API signature as the .write_end of
+ * simple_write_end does the minimum needed for updating a folio after
+ * writing is done. It has the same API signature as the .write_end of
  * address_space_operations vector. So it can just be set onto .write_end for
  * FSes that don't need any other processing. i_mutex is assumed to be held.
  * Block based filesystems should use generic_write_end().
@@ -946,9 +946,8 @@ EXPORT_SYMBOL(simple_write_begin);
  */
 static int simple_write_end(struct file *file, struct address_space *mapping,
 			loff_t pos, unsigned len, unsigned copied,
-			struct page *page, void *fsdata)
+			struct folio *folio, void *fsdata)
 {
-	struct folio *folio = page_folio(page);
 	struct inode *inode = folio->mapping->host;
 	loff_t last_pos = pos + copied;
 
diff --git a/fs/namei.c b/fs/namei.c
index 80e48a440c1f..c65c03bc3703 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -5325,7 +5325,7 @@ int page_symlink(struct inode *inode, const char *symname, int len)
 	memcpy(page_address(page), symname, len-1);
 
 	err = aops->write_end(NULL, mapping, 0, len-1, len-1,
-							page, fsdata);
+						page_folio(page), fsdata);
 	if (err < 0)
 		goto fail;
 	if (err < len-1)
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index 61a8cdb9f1e1..fe583dbebe54 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -372,10 +372,9 @@ static int nfs_write_begin(struct file *file, struct address_space *mapping,
 
 static int nfs_write_end(struct file *file, struct address_space *mapping,
 			 loff_t pos, unsigned len, unsigned copied,
-			 struct page *page, void *fsdata)
+			 struct folio *folio, void *fsdata)
 {
 	struct nfs_open_context *ctx = nfs_file_open_context(file);
-	struct folio *folio = page_folio(page);
 	unsigned offset = offset_in_folio(folio, pos);
 	int status;
 
diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c
index 7340a01d80e1..25841b75415a 100644
--- a/fs/nilfs2/inode.c
+++ b/fs/nilfs2/inode.c
@@ -269,16 +269,16 @@ static int nilfs_write_begin(struct file *file, struct address_space *mapping,
 
 static int nilfs_write_end(struct file *file, struct address_space *mapping,
 			   loff_t pos, unsigned len, unsigned copied,
-			   struct page *page, void *fsdata)
+			   struct folio *folio, void *fsdata)
 {
 	struct inode *inode = mapping->host;
 	unsigned int start = pos & (PAGE_SIZE - 1);
 	unsigned int nr_dirty;
 	int err;
 
-	nr_dirty = nilfs_page_count_clean_buffers(page, start,
+	nr_dirty = nilfs_page_count_clean_buffers(&folio->page, start,
 						  start + copied);
-	copied = generic_write_end(file, mapping, pos, len, copied, page,
+	copied = generic_write_end(file, mapping, pos, len, copied, folio,
 				   fsdata);
 	nilfs_set_file_dirty(inode, nr_dirty);
 	err = nilfs_transaction_commit(inode->i_sb);
diff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c
index ca1ddc46bd86..88a7d81cf2ba 100644
--- a/fs/ntfs3/file.c
+++ b/fs/ntfs3/file.c
@@ -215,7 +215,7 @@ static int ntfs_extend_initialized_size(struct file *file,
 		zero_user_segment(page, zerofrom, PAGE_SIZE);
 
 		/* This function in any case puts page. */
-		err = ntfs_write_end(file, mapping, pos, len, len, page, NULL);
+		err = ntfs_write_end(file, mapping, pos, len, len, page_folio(page), NULL);
 		if (err < 0)
 			goto out;
 		pos += len;
diff --git a/fs/ntfs3/inode.c b/fs/ntfs3/inode.c
index 8eaaf9e465d4..9efd3f7c59d6 100644
--- a/fs/ntfs3/inode.c
+++ b/fs/ntfs3/inode.c
@@ -947,9 +947,8 @@ int ntfs_write_begin(struct file *file, struct address_space *mapping,
  * ntfs_write_end - Address_space_operations::write_end.
  */
 int ntfs_write_end(struct file *file, struct address_space *mapping, loff_t pos,
-		   u32 len, u32 copied, struct page *page, void *fsdata)
+		   u32 len, u32 copied, struct folio *folio, void *fsdata)
 {
-	struct folio *folio = page_folio(page);
 	struct inode *inode = mapping->host;
 	struct ntfs_inode *ni = ntfs_i(inode);
 	u64 valid = ni->i_valid;
@@ -979,7 +978,7 @@ int ntfs_write_end(struct file *file, struct address_space *mapping, loff_t pos,
 		folio_unlock(folio);
 		folio_put(folio);
 	} else {
-		err = generic_write_end(file, mapping, pos, len, copied, page,
+		err = generic_write_end(file, mapping, pos, len, copied, folio,
 					fsdata);
 	}
 
diff --git a/fs/ntfs3/ntfs_fs.h b/fs/ntfs3/ntfs_fs.h
index 4e363b8342d6..53517281f26b 100644
--- a/fs/ntfs3/ntfs_fs.h
+++ b/fs/ntfs3/ntfs_fs.h
@@ -713,7 +713,7 @@ int ntfs_get_block(struct inode *inode, sector_t vbn,
 int ntfs_write_begin(struct file *file, struct address_space *mapping,
 		     loff_t pos, u32 len, struct page **pagep, void **fsdata);
 int ntfs_write_end(struct file *file, struct address_space *mapping, loff_t pos,
-		   u32 len, u32 copied, struct page *page, void *fsdata);
+		   u32 len, u32 copied, struct folio *folio, void *fsdata);
 int ntfs3_write_inode(struct inode *inode, struct writeback_control *wbc);
 int ntfs_sync_inode(struct inode *inode);
 int ntfs_flush_inodes(struct super_block *sb, struct inode *i1,
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c
index 6be175a1ab3c..9d8aa417e8da 100644
--- a/fs/ocfs2/aops.c
+++ b/fs/ocfs2/aops.c
@@ -2076,7 +2076,7 @@ int ocfs2_write_end_nolock(struct address_space *mapping,
 
 static int ocfs2_write_end(struct file *file, struct address_space *mapping,
 			   loff_t pos, unsigned len, unsigned copied,
-			   struct page *page, void *fsdata)
+			   struct folio *folio, void *fsdata)
 {
 	int ret;
 	struct inode *inode = mapping->host;
diff --git a/fs/orangefs/inode.c b/fs/orangefs/inode.c
index e8440fa7d73c..69b507a611f8 100644
--- a/fs/orangefs/inode.c
+++ b/fs/orangefs/inode.c
@@ -361,9 +361,9 @@ static int orangefs_write_begin(struct file *file,
 }
 
 static int orangefs_write_end(struct file *file, struct address_space *mapping,
-    loff_t pos, unsigned len, unsigned copied, struct page *page, void *fsdata)
+		loff_t pos, unsigned len, unsigned copied, struct folio *folio,
+		void *fsdata)
 {
-	struct folio *folio = page_folio(page);
 	struct inode *inode = folio->mapping->host;
 	loff_t last_pos = pos + copied;
 
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index 33da519c9767..f4b9db4b4df2 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -2862,10 +2862,9 @@ static sector_t reiserfs_aop_bmap(struct address_space *as, sector_t block)
 
 static int reiserfs_write_end(struct file *file, struct address_space *mapping,
 			      loff_t pos, unsigned len, unsigned copied,
-			      struct page *page, void *fsdata)
+			      struct folio *folio, void *fsdata)
 {
-	struct folio *folio = page_folio(page);
-	struct inode *inode = page->mapping->host;
+	struct inode *inode = folio->mapping->host;
 	int ret = 0;
 	int update_sd = 0;
 	struct reiserfs_transaction_handle *th;
@@ -2887,7 +2886,7 @@ static int reiserfs_write_end(struct file *file, struct address_space *mapping,
 	}
 	flush_dcache_folio(folio);
 
-	reiserfs_commit_page(inode, page, start, start + copied);
+	reiserfs_commit_page(inode, &folio->page, start, start + copied);
 
 	/*
 	 * generic_commit_write does this for us, but does not update the
@@ -2942,8 +2941,8 @@ static int reiserfs_write_end(struct file *file, struct address_space *mapping,
 out:
 	if (locked)
 		reiserfs_write_unlock(inode->i_sb);
-	unlock_page(page);
-	put_page(page);
+	folio_unlock(folio);
+	folio_put(folio);
 
 	if (pos + len > inode->i_size)
 		reiserfs_truncate_failed_write(inode);
diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c
index 68e104423a48..baa3eecc32fe 100644
--- a/fs/ubifs/file.c
+++ b/fs/ubifs/file.c
@@ -524,9 +524,8 @@ static void cancel_budget(struct ubifs_info *c, struct folio *folio,
 
 static int ubifs_write_end(struct file *file, struct address_space *mapping,
 			   loff_t pos, unsigned len, unsigned copied,
-			   struct page *page, void *fsdata)
+			   struct folio *folio, void *fsdata)
 {
-	struct folio *folio = page_folio(page);
 	struct inode *inode = mapping->host;
 	struct ubifs_inode *ui = ubifs_inode(inode);
 	struct ubifs_info *c = inode->i_sb->s_fs_info;
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index 4726a4d014b6..fdf024e0b772 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -273,16 +273,14 @@ static int udf_write_begin(struct file *file, struct address_space *mapping,
 
 static int udf_write_end(struct file *file, struct address_space *mapping,
 			 loff_t pos, unsigned len, unsigned copied,
-			 struct page *page, void *fsdata)
+			 struct folio *folio, void *fsdata)
 {
 	struct inode *inode = file_inode(file);
-	struct folio *folio;
 	loff_t last_pos;
 
 	if (UDF_I(inode)->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB)
-		return generic_write_end(file, mapping, pos, len, copied, page,
+		return generic_write_end(file, mapping, pos, len, copied, folio,
 					 fsdata);
-	folio = page_folio(page);
 	last_pos = pos + copied;
 	if (last_pos > inode->i_size)
 		i_size_write(inode, last_pos);
diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c
index 0e608fc0d0fd..69adb198c634 100644
--- a/fs/ufs/inode.c
+++ b/fs/ufs/inode.c
@@ -511,11 +511,11 @@ static int ufs_write_begin(struct file *file, struct address_space *mapping,
 
 static int ufs_write_end(struct file *file, struct address_space *mapping,
 			loff_t pos, unsigned len, unsigned copied,
-			struct page *page, void *fsdata)
+			struct folio *folio, void *fsdata)
 {
 	int ret;
 
-	ret = generic_write_end(file, mapping, pos, len, copied, page, fsdata);
+	ret = generic_write_end(file, mapping, pos, len, copied, folio, fsdata);
 	if (ret < len)
 		ufs_write_failed(mapping, pos + len);
 	return ret;
diff --git a/fs/vboxsf/file.c b/fs/vboxsf/file.c
index 029f106d56d9..b780deb81b02 100644
--- a/fs/vboxsf/file.c
+++ b/fs/vboxsf/file.c
@@ -300,9 +300,8 @@ static int vboxsf_writepage(struct page *page, struct writeback_control *wbc)
 
 static int vboxsf_write_end(struct file *file, struct address_space *mapping,
 			    loff_t pos, unsigned int len, unsigned int copied,
-			    struct page *page, void *fsdata)
+			    struct folio *folio, void *fsdata)
 {
-	struct folio *folio = page_folio(page);
 	struct inode *inode = mapping->host;
 	struct vboxsf_handle *sf_handle = file->private_data;
 	size_t from = offset_in_folio(folio, pos);
@@ -314,10 +313,10 @@ static int vboxsf_write_end(struct file *file, struct address_space *mapping,
 	if (!folio_test_uptodate(folio) && copied < len)
 		folio_zero_range(folio, from + copied, len - copied);
 
-	buf = kmap(page);
+	buf = kmap(&folio->page);
 	err = vboxsf_write(sf_handle->root, sf_handle->handle,
 			   pos, &nwritten, buf + from);
-	kunmap(page);
+	kunmap(&folio->page);
 
 	if (err) {
 		nwritten = 0;
diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h
index 3a3fec154536..165e859664a5 100644
--- a/include/linux/buffer_head.h
+++ b/include/linux/buffer_head.h
@@ -265,8 +265,8 @@ int block_write_end(struct file *, struct address_space *,
 				loff_t, unsigned len, unsigned copied,
 				struct folio *, void *);
 int generic_write_end(struct file *, struct address_space *,
-				loff_t, unsigned, unsigned,
-				struct page *, void *);
+				loff_t, unsigned len, unsigned copied,
+				struct folio *, void *);
 void folio_zero_new_buffers(struct folio *folio, size_t from, size_t to);
 int cont_write_begin(struct file *, struct address_space *, loff_t,
 			unsigned, struct page **, void **,
diff --git a/include/linux/fs.h b/include/linux/fs.h
index ea3df718c53e..6ff85d72067b 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -411,7 +411,7 @@ struct address_space_operations {
 				struct page **pagep, void **fsdata);
 	int (*write_end)(struct file *, struct address_space *mapping,
 				loff_t pos, unsigned len, unsigned copied,
-				struct page *page, void *fsdata);
+				struct folio *folio, void *fsdata);
 
 	/* Unfortunately this kludge is needed for FIBMAP. Don't use it */
 	sector_t (*bmap)(struct address_space *, sector_t);
diff --git a/mm/filemap.c b/mm/filemap.c
index d62150418b91..fab6b0c3044e 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -4033,7 +4033,7 @@ ssize_t generic_perform_write(struct kiocb *iocb, struct iov_iter *i)
 		flush_dcache_folio(folio);
 
 		status = a_ops->write_end(file, mapping, pos, bytes, copied,
-						page, fsdata);
+						folio, fsdata);
 		if (unlikely(status != copied)) {
 			iov_iter_revert(i, copied - max(status, 0L));
 			if (unlikely(status < 0))
diff --git a/mm/shmem.c b/mm/shmem.c
index 2faa9daaf54b..1116f147d788 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -2917,9 +2917,8 @@ shmem_write_begin(struct file *file, struct address_space *mapping,
 static int
 shmem_write_end(struct file *file, struct address_space *mapping,
 			loff_t pos, unsigned len, unsigned copied,
-			struct page *page, void *fsdata)
+			struct folio *folio, void *fsdata)
 {
-	struct folio *folio = page_folio(page);
 	struct inode *inode = mapping->host;
 
 	if (pos + copied > inode->i_size)
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 21/23] fs: Convert aops->write_begin to take a folio
  2024-07-17 15:46 [PATCH 00/23] Convert write_begin / write_end to take a folio Matthew Wilcox (Oracle)
                   ` (19 preceding siblings ...)
  2024-07-17 15:47 ` [PATCH 20/23] fs: Convert aops->write_end to take a folio Matthew Wilcox (Oracle)
@ 2024-07-17 15:47 ` Matthew Wilcox (Oracle)
  2024-07-17 15:47 ` [PATCH 22/23] ocfs2: Convert ocfs2_write_zero_page to use " Matthew Wilcox (Oracle)
                   ` (3 subsequent siblings)
  24 siblings, 0 replies; 31+ messages in thread
From: Matthew Wilcox (Oracle) @ 2024-07-17 15:47 UTC (permalink / raw)
  To: linux-fsdevel; +Cc: Matthew Wilcox (Oracle)

Convert all callers from working on a page to working on one page
of a folio (support for working on an entire folio can come later).
Removes a lot of folio->page->folio conversions.

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
 Documentation/filesystems/locking.rst     |  4 +-
 Documentation/filesystems/vfs.rst         |  6 +--
 block/fops.c                              |  4 +-
 drivers/gpu/drm/i915/gem/i915_gem_shmem.c | 47 +++++++++++------------
 fs/adfs/inode.c                           |  5 +--
 fs/affs/file.c                            | 15 ++++----
 fs/bcachefs/fs-io-buffered.c              |  5 +--
 fs/bcachefs/fs-io-buffered.h              |  4 +-
 fs/bfs/file.c                             |  4 +-
 fs/buffer.c                               | 28 +++++++-------
 fs/ceph/addr.c                            | 10 ++---
 fs/ecryptfs/mmap.c                        |  7 ++--
 fs/exfat/file.c                           |  8 ++--
 fs/exfat/inode.c                          |  5 +--
 fs/ext2/inode.c                           |  4 +-
 fs/ext4/ext4.h                            |  4 +-
 fs/ext4/inline.c                          |  8 ++--
 fs/ext4/inode.c                           | 14 +++----
 fs/ext4/verity.c                          |  8 ++--
 fs/f2fs/data.c                            |  8 ++--
 fs/f2fs/super.c                           |  8 ++--
 fs/f2fs/verity.c                          |  8 ++--
 fs/fat/inode.c                            |  5 +--
 fs/fuse/file.c                            |  4 +-
 fs/hfs/extent.c                           |  6 +--
 fs/hfs/hfs_fs.h                           |  2 +-
 fs/hfs/inode.c                            |  5 +--
 fs/hfsplus/extents.c                      |  6 +--
 fs/hfsplus/hfsplus_fs.h                   |  2 +-
 fs/hfsplus/inode.c                        |  5 +--
 fs/hostfs/hostfs_kern.c                   |  7 ++--
 fs/hpfs/file.c                            |  5 +--
 fs/hugetlbfs/inode.c                      |  2 +-
 fs/jffs2/file.c                           |  6 +--
 fs/jfs/inode.c                            |  4 +-
 fs/libfs.c                                |  4 +-
 fs/minix/inode.c                          |  4 +-
 fs/namei.c                                | 10 ++---
 fs/nfs/file.c                             |  4 +-
 fs/nilfs2/inode.c                         |  4 +-
 fs/nilfs2/recovery.c                      |  6 +--
 fs/ntfs3/file.c                           |  9 ++---
 fs/ntfs3/inode.c                          |  7 ++--
 fs/ntfs3/ntfs_fs.h                        |  2 +-
 fs/ocfs2/aops.c                           | 10 ++---
 fs/ocfs2/aops.h                           |  2 +-
 fs/ocfs2/mmap.c                           |  6 +--
 fs/omfs/file.c                            |  4 +-
 fs/orangefs/inode.c                       |  4 +-
 fs/reiserfs/inode.c                       |  4 +-
 fs/sysv/itree.c                           |  4 +-
 fs/ubifs/file.c                           | 10 ++---
 fs/udf/inode.c                            |  6 +--
 fs/ufs/inode.c                            |  4 +-
 include/linux/buffer_head.h               |  4 +-
 include/linux/fs.h                        |  4 +-
 mm/filemap.c                              |  4 +-
 mm/shmem.c                                |  7 ++--
 58 files changed, 189 insertions(+), 207 deletions(-)

diff --git a/Documentation/filesystems/locking.rst b/Documentation/filesystems/locking.rst
index 827fb5a073b7..f5e3676db954 100644
--- a/Documentation/filesystems/locking.rst
+++ b/Documentation/filesystems/locking.rst
@@ -251,7 +251,7 @@ prototypes::
 	void (*readahead)(struct readahead_control *);
 	int (*write_begin)(struct file *, struct address_space *mapping,
 				loff_t pos, unsigned len,
-				struct page **pagep, void **fsdata);
+				struct folio **foliop, void **fsdata);
 	int (*write_end)(struct file *, struct address_space *mapping,
 				loff_t pos, unsigned len, unsigned copied,
 				struct folio *folio, void *fsdata);
@@ -280,7 +280,7 @@ read_folio:		yes, unlocks				shared
 writepages:
 dirty_folio:		maybe
 readahead:		yes, unlocks				shared
-write_begin:		locks the page		 exclusive
+write_begin:		locks the folio		 exclusive
 write_end:		yes, unlocks		 exclusive
 bmap:
 invalidate_folio:	yes					exclusive
diff --git a/Documentation/filesystems/vfs.rst b/Documentation/filesystems/vfs.rst
index 0e24f770c568..4f67b5ea0568 100644
--- a/Documentation/filesystems/vfs.rst
+++ b/Documentation/filesystems/vfs.rst
@@ -926,12 +926,12 @@ cache in your filesystem.  The following members are defined:
 	(if they haven't been read already) so that the updated blocks
 	can be written out properly.
 
-	The filesystem must return the locked pagecache page for the
-	specified offset, in ``*pagep``, for the caller to write into.
+	The filesystem must return the locked pagecache folio for the
+	specified offset, in ``*foliop``, for the caller to write into.
 
 	It must be able to cope with short writes (where the length
 	passed to write_begin is greater than the number of bytes copied
-	into the page).
+	into the folio).
 
 	A void * may be returned in fsdata, which then gets passed into
 	write_end.
diff --git a/block/fops.c b/block/fops.c
index cd96a6f17119..dacbd61fda29 100644
--- a/block/fops.c
+++ b/block/fops.c
@@ -451,9 +451,9 @@ static void blkdev_readahead(struct readahead_control *rac)
 }
 
 static int blkdev_write_begin(struct file *file, struct address_space *mapping,
-		loff_t pos, unsigned len, struct page **pagep, void **fsdata)
+		loff_t pos, unsigned len, struct folio **foliop, void **fsdata)
 {
-	return block_write_begin(mapping, pos, len, pagep, blkdev_get_block);
+	return block_write_begin(mapping, pos, len, foliop, blkdev_get_block);
 }
 
 static int blkdev_write_end(struct file *file, struct address_space *mapping,
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_shmem.c b/drivers/gpu/drm/i915/gem/i915_gem_shmem.c
index 3513165a2964..fe69f2c8527d 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_shmem.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_shmem.c
@@ -424,7 +424,8 @@ shmem_pwrite(struct drm_i915_gem_object *obj,
 	struct address_space *mapping = obj->base.filp->f_mapping;
 	const struct address_space_operations *aops = mapping->a_ops;
 	char __user *user_data = u64_to_user_ptr(arg->data_ptr);
-	u64 remain, offset;
+	u64 remain;
+	loff_t pos;
 	unsigned int pg;
 
 	/* Caller already validated user args */
@@ -457,12 +458,12 @@ shmem_pwrite(struct drm_i915_gem_object *obj,
 	 */
 
 	remain = arg->size;
-	offset = arg->offset;
-	pg = offset_in_page(offset);
+	pos = arg->offset;
+	pg = offset_in_page(pos);
 
 	do {
 		unsigned int len, unwritten;
-		struct page *page;
+		struct folio *folio;
 		void *data, *vaddr;
 		int err;
 		char __maybe_unused c;
@@ -480,21 +481,19 @@ shmem_pwrite(struct drm_i915_gem_object *obj,
 		if (err)
 			return err;
 
-		err = aops->write_begin(obj->base.filp, mapping, offset, len,
-					&page, &data);
+		err = aops->write_begin(obj->base.filp, mapping, pos, len,
+					&folio, &data);
 		if (err < 0)
 			return err;
 
-		vaddr = kmap_local_page(page);
+		vaddr = kmap_local_folio(folio, offset_in_folio(folio, pos));
 		pagefault_disable();
-		unwritten = __copy_from_user_inatomic(vaddr + pg,
-						      user_data,
-						      len);
+		unwritten = __copy_from_user_inatomic(vaddr, user_data, len);
 		pagefault_enable();
 		kunmap_local(vaddr);
 
-		err = aops->write_end(obj->base.filp, mapping, offset, len,
-				      len - unwritten, page_folio(page), data);
+		err = aops->write_end(obj->base.filp, mapping, pos, len,
+				      len - unwritten, folio, data);
 		if (err < 0)
 			return err;
 
@@ -504,7 +503,7 @@ shmem_pwrite(struct drm_i915_gem_object *obj,
 
 		remain -= len;
 		user_data += len;
-		offset += len;
+		pos += len;
 		pg = 0;
 	} while (remain);
 
@@ -660,7 +659,7 @@ i915_gem_object_create_shmem_from_data(struct drm_i915_private *i915,
 	struct drm_i915_gem_object *obj;
 	struct file *file;
 	const struct address_space_operations *aops;
-	resource_size_t offset;
+	loff_t pos;
 	int err;
 
 	GEM_WARN_ON(IS_DGFX(i915));
@@ -672,29 +671,27 @@ i915_gem_object_create_shmem_from_data(struct drm_i915_private *i915,
 
 	file = obj->base.filp;
 	aops = file->f_mapping->a_ops;
-	offset = 0;
+	pos = 0;
 	do {
 		unsigned int len = min_t(typeof(size), size, PAGE_SIZE);
-		struct page *page;
-		void *pgdata, *vaddr;
+		struct folio *folio;
+		void *fsdata;
 
-		err = aops->write_begin(file, file->f_mapping, offset, len,
-					&page, &pgdata);
+		err = aops->write_begin(file, file->f_mapping, pos, len,
+					&folio, &fsdata);
 		if (err < 0)
 			goto fail;
 
-		vaddr = kmap(page);
-		memcpy(vaddr, data, len);
-		kunmap(page);
+		memcpy_to_folio(folio, offset_in_folio(folio, pos), data, len);
 
-		err = aops->write_end(file, file->f_mapping, offset, len, len,
-				      page_folio(page), pgdata);
+		err = aops->write_end(file, file->f_mapping, pos, len, len,
+				      folio, fsdata);
 		if (err < 0)
 			goto fail;
 
 		size -= len;
 		data += len;
-		offset += len;
+		pos += len;
 	} while (size);
 
 	return obj;
diff --git a/fs/adfs/inode.c b/fs/adfs/inode.c
index a183e213a4a5..21527189e430 100644
--- a/fs/adfs/inode.c
+++ b/fs/adfs/inode.c
@@ -55,12 +55,11 @@ static void adfs_write_failed(struct address_space *mapping, loff_t to)
 
 static int adfs_write_begin(struct file *file, struct address_space *mapping,
 			loff_t pos, unsigned len,
-			struct page **pagep, void **fsdata)
+			struct folio **foliop, void **fsdata)
 {
 	int ret;
 
-	*pagep = NULL;
-	ret = cont_write_begin(file, mapping, pos, len, pagep, fsdata,
+	ret = cont_write_begin(file, mapping, pos, len, foliop, fsdata,
 				adfs_get_block,
 				&ADFS_I(mapping->host)->mmu_private);
 	if (unlikely(ret))
diff --git a/fs/affs/file.c b/fs/affs/file.c
index 6a6c5bc41b8f..a5a861dd5223 100644
--- a/fs/affs/file.c
+++ b/fs/affs/file.c
@@ -417,12 +417,11 @@ affs_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
 
 static int affs_write_begin(struct file *file, struct address_space *mapping,
 			loff_t pos, unsigned len,
-			struct page **pagep, void **fsdata)
+			struct folio **foliop, void **fsdata)
 {
 	int ret;
 
-	*pagep = NULL;
-	ret = cont_write_begin(file, mapping, pos, len, pagep, fsdata,
+	ret = cont_write_begin(file, mapping, pos, len, foliop, fsdata,
 				affs_get_block,
 				&AFFS_I(mapping->host)->mmu_private);
 	if (unlikely(ret))
@@ -648,7 +647,7 @@ static int affs_read_folio_ofs(struct file *file, struct folio *folio)
 
 static int affs_write_begin_ofs(struct file *file, struct address_space *mapping,
 				loff_t pos, unsigned len,
-				struct page **pagep, void **fsdata)
+				struct folio **foliop, void **fsdata)
 {
 	struct inode *inode = mapping->host;
 	struct folio *folio;
@@ -671,7 +670,7 @@ static int affs_write_begin_ofs(struct file *file, struct address_space *mapping
 			mapping_gfp_mask(mapping));
 	if (IS_ERR(folio))
 		return PTR_ERR(folio);
-	*pagep = &folio->page;
+	*foliop = folio;
 
 	if (folio_test_uptodate(folio))
 		return 0;
@@ -881,14 +880,14 @@ affs_truncate(struct inode *inode)
 
 	if (inode->i_size > AFFS_I(inode)->mmu_private) {
 		struct address_space *mapping = inode->i_mapping;
-		struct page *page;
+		struct folio *folio;
 		void *fsdata = NULL;
 		loff_t isize = inode->i_size;
 		int res;
 
-		res = mapping->a_ops->write_begin(NULL, mapping, isize, 0, &page, &fsdata);
+		res = mapping->a_ops->write_begin(NULL, mapping, isize, 0, &folio, &fsdata);
 		if (!res)
-			res = mapping->a_ops->write_end(NULL, mapping, isize, 0, 0, page_folio(page), fsdata);
+			res = mapping->a_ops->write_end(NULL, mapping, isize, 0, 0, folio, fsdata);
 		else
 			inode->i_size = AFFS_I(inode)->mmu_private;
 		mark_inode_dirty(inode);
diff --git a/fs/bcachefs/fs-io-buffered.c b/fs/bcachefs/fs-io-buffered.c
index 46ae9ef3589a..3d410d801825 100644
--- a/fs/bcachefs/fs-io-buffered.c
+++ b/fs/bcachefs/fs-io-buffered.c
@@ -659,7 +659,7 @@ int bch2_writepages(struct address_space *mapping, struct writeback_control *wbc
 
 int bch2_write_begin(struct file *file, struct address_space *mapping,
 		     loff_t pos, unsigned len,
-		     struct page **pagep, void **fsdata)
+		     struct folio **foliop, void **fsdata)
 {
 	struct bch_inode_info *inode = to_bch_ei(mapping->host);
 	struct bch_fs *c = inode->v.i_sb->s_fs_info;
@@ -728,12 +728,11 @@ int bch2_write_begin(struct file *file, struct address_space *mapping,
 		goto err;
 	}
 
-	*pagep = &folio->page;
+	*foliop = folio;
 	return 0;
 err:
 	folio_unlock(folio);
 	folio_put(folio);
-	*pagep = NULL;
 err_unlock:
 	bch2_pagecache_add_put(inode);
 	kfree(res);
diff --git a/fs/bcachefs/fs-io-buffered.h b/fs/bcachefs/fs-io-buffered.h
index 16569b9874e0..3207ebbb4ab4 100644
--- a/fs/bcachefs/fs-io-buffered.h
+++ b/fs/bcachefs/fs-io-buffered.h
@@ -10,8 +10,8 @@ int bch2_read_folio(struct file *, struct folio *);
 int bch2_writepages(struct address_space *, struct writeback_control *);
 void bch2_readahead(struct readahead_control *);
 
-int bch2_write_begin(struct file *, struct address_space *, loff_t,
-		     unsigned, struct page **, void **);
+int bch2_write_begin(struct file *, struct address_space *, loff_t pos,
+		     unsigned len, struct folio **, void **);
 int bch2_write_end(struct file *, struct address_space *, loff_t,
 		   unsigned len, unsigned copied, struct folio *, void *);
 
diff --git a/fs/bfs/file.c b/fs/bfs/file.c
index a778411574a9..fa66a09e496a 100644
--- a/fs/bfs/file.c
+++ b/fs/bfs/file.c
@@ -172,11 +172,11 @@ static void bfs_write_failed(struct address_space *mapping, loff_t to)
 
 static int bfs_write_begin(struct file *file, struct address_space *mapping,
 			loff_t pos, unsigned len,
-			struct page **pagep, void **fsdata)
+			struct folio **foliop, void **fsdata)
 {
 	int ret;
 
-	ret = block_write_begin(mapping, pos, len, pagep, bfs_get_block);
+	ret = block_write_begin(mapping, pos, len, foliop, bfs_get_block);
 	if (unlikely(ret))
 		bfs_write_failed(mapping, pos + len);
 
diff --git a/fs/buffer.c b/fs/buffer.c
index 1a0f2f65e890..d52a740f7fca 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -2222,7 +2222,7 @@ static void __block_commit_write(struct folio *folio, size_t from, size_t to)
  * The filesystem needs to handle block truncation upon failure.
  */
 int block_write_begin(struct address_space *mapping, loff_t pos, unsigned len,
-		struct page **pagep, get_block_t *get_block)
+		struct folio **foliop, get_block_t *get_block)
 {
 	pgoff_t index = pos >> PAGE_SHIFT;
 	struct folio *folio;
@@ -2240,7 +2240,7 @@ int block_write_begin(struct address_space *mapping, loff_t pos, unsigned len,
 		folio = NULL;
 	}
 
-	*pagep = &folio->page;
+	*foliop = folio;
 	return status;
 }
 EXPORT_SYMBOL(block_write_begin);
@@ -2467,7 +2467,7 @@ int generic_cont_expand_simple(struct inode *inode, loff_t size)
 {
 	struct address_space *mapping = inode->i_mapping;
 	const struct address_space_operations *aops = mapping->a_ops;
-	struct page *page;
+	struct folio *folio;
 	void *fsdata = NULL;
 	int err;
 
@@ -2475,11 +2475,11 @@ int generic_cont_expand_simple(struct inode *inode, loff_t size)
 	if (err)
 		goto out;
 
-	err = aops->write_begin(NULL, mapping, size, 0, &page, &fsdata);
+	err = aops->write_begin(NULL, mapping, size, 0, &folio, &fsdata);
 	if (err)
 		goto out;
 
-	err = aops->write_end(NULL, mapping, size, 0, 0, page_folio(page), fsdata);
+	err = aops->write_end(NULL, mapping, size, 0, 0, folio, fsdata);
 	BUG_ON(err > 0);
 
 out:
@@ -2493,7 +2493,7 @@ static int cont_expand_zero(struct file *file, struct address_space *mapping,
 	struct inode *inode = mapping->host;
 	const struct address_space_operations *aops = mapping->a_ops;
 	unsigned int blocksize = i_blocksize(inode);
-	struct page *page;
+	struct folio *folio;
 	void *fsdata = NULL;
 	pgoff_t index, curidx;
 	loff_t curpos;
@@ -2512,12 +2512,12 @@ static int cont_expand_zero(struct file *file, struct address_space *mapping,
 		len = PAGE_SIZE - zerofrom;
 
 		err = aops->write_begin(file, mapping, curpos, len,
-					    &page, &fsdata);
+					    &folio, &fsdata);
 		if (err)
 			goto out;
-		zero_user(page, zerofrom, len);
+		folio_zero_range(folio, offset_in_folio(folio, curpos), len);
 		err = aops->write_end(file, mapping, curpos, len, len,
-						page_folio(page), fsdata);
+						folio, fsdata);
 		if (err < 0)
 			goto out;
 		BUG_ON(err != len);
@@ -2545,12 +2545,12 @@ static int cont_expand_zero(struct file *file, struct address_space *mapping,
 		len = offset - zerofrom;
 
 		err = aops->write_begin(file, mapping, curpos, len,
-					    &page, &fsdata);
+					    &folio, &fsdata);
 		if (err)
 			goto out;
-		zero_user(page, zerofrom, len);
+		folio_zero_range(folio, offset_in_folio(folio, curpos), len);
 		err = aops->write_end(file, mapping, curpos, len, len,
-						page_folio(page), fsdata);
+						folio, fsdata);
 		if (err < 0)
 			goto out;
 		BUG_ON(err != len);
@@ -2566,7 +2566,7 @@ static int cont_expand_zero(struct file *file, struct address_space *mapping,
  */
 int cont_write_begin(struct file *file, struct address_space *mapping,
 			loff_t pos, unsigned len,
-			struct page **pagep, void **fsdata,
+			struct folio **foliop, void **fsdata,
 			get_block_t *get_block, loff_t *bytes)
 {
 	struct inode *inode = mapping->host;
@@ -2584,7 +2584,7 @@ int cont_write_begin(struct file *file, struct address_space *mapping,
 		(*bytes)++;
 	}
 
-	return block_write_begin(mapping, pos, len, pagep, get_block);
+	return block_write_begin(mapping, pos, len, foliop, get_block);
 }
 EXPORT_SYMBOL(cont_write_begin);
 
diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c
index 87369e2659c7..4402cddf82b5 100644
--- a/fs/ceph/addr.c
+++ b/fs/ceph/addr.c
@@ -1486,20 +1486,18 @@ static int ceph_netfs_check_write_begin(struct file *file, loff_t pos, unsigned
  */
 static int ceph_write_begin(struct file *file, struct address_space *mapping,
 			    loff_t pos, unsigned len,
-			    struct page **pagep, void **fsdata)
+			    struct folio **foliop, void **fsdata)
 {
 	struct inode *inode = file_inode(file);
 	struct ceph_inode_info *ci = ceph_inode(inode);
-	struct folio *folio = NULL;
 	int r;
 
-	r = netfs_write_begin(&ci->netfs, file, inode->i_mapping, pos, len, &folio, NULL);
+	r = netfs_write_begin(&ci->netfs, file, inode->i_mapping, pos, len, foliop, NULL);
 	if (r < 0)
 		return r;
 
-	folio_wait_private_2(folio); /* [DEPRECATED] */
-	WARN_ON_ONCE(!folio_test_locked(folio));
-	*pagep = &folio->page;
+	folio_wait_private_2(*foliop); /* [DEPRECATED] */
+	WARN_ON_ONCE(!folio_test_locked(*foliop));
 	return 0;
 }
 
diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c
index f43e42ede75e..287e5d407f08 100644
--- a/fs/ecryptfs/mmap.c
+++ b/fs/ecryptfs/mmap.c
@@ -255,7 +255,7 @@ static int fill_zeros_to_end_of_page(struct folio *folio, unsigned int to)
  * @mapping: The eCryptfs object
  * @pos: The file offset at which to start writing
  * @len: Length of the write
- * @pagep: Pointer to return the page
+ * @foliop: Pointer to return the folio
  * @fsdata: Pointer to return fs data (unused)
  *
  * This function must zero any hole we create
@@ -265,7 +265,7 @@ static int fill_zeros_to_end_of_page(struct folio *folio, unsigned int to)
 static int ecryptfs_write_begin(struct file *file,
 			struct address_space *mapping,
 			loff_t pos, unsigned len,
-			struct page **pagep, void **fsdata)
+			struct folio **foliop, void **fsdata)
 {
 	pgoff_t index = pos >> PAGE_SHIFT;
 	struct folio *folio;
@@ -276,7 +276,7 @@ static int ecryptfs_write_begin(struct file *file,
 			mapping_gfp_mask(mapping));
 	if (IS_ERR(folio))
 		return PTR_ERR(folio);
-	*pagep = &folio->page;
+	*foliop = folio;
 
 	prev_page_end_size = ((loff_t)index << PAGE_SHIFT);
 	if (!folio_test_uptodate(folio)) {
@@ -365,7 +365,6 @@ static int ecryptfs_write_begin(struct file *file,
 	if (unlikely(rc)) {
 		folio_unlock(folio);
 		folio_put(folio);
-		*pagep = NULL;
 	}
 	return rc;
 }
diff --git a/fs/exfat/file.c b/fs/exfat/file.c
index 7144472d092e..e19469e88000 100644
--- a/fs/exfat/file.c
+++ b/fs/exfat/file.c
@@ -535,20 +535,20 @@ static int exfat_file_zeroed_range(struct file *file, loff_t start, loff_t end)
 
 	while (start < end) {
 		u32 zerofrom, len;
-		struct page *page = NULL;
+		struct folio *folio;
 
 		zerofrom = start & (PAGE_SIZE - 1);
 		len = PAGE_SIZE - zerofrom;
 		if (start + len > end)
 			len = end - start;
 
-		err = ops->write_begin(file, mapping, start, len, &page, NULL);
+		err = ops->write_begin(file, mapping, start, len, &folio, NULL);
 		if (err)
 			goto out;
 
-		zero_user_segment(page, zerofrom, zerofrom + len);
+		folio_zero_range(folio, offset_in_folio(folio, start), len);
 
-		err = ops->write_end(file, mapping, start, len, len, page_folio(page), NULL);
+		err = ops->write_end(file, mapping, start, len, len, folio, NULL);
 		if (err < 0)
 			goto out;
 		start += len;
diff --git a/fs/exfat/inode.c b/fs/exfat/inode.c
index 871e9e3e407e..05f0e07b01d0 100644
--- a/fs/exfat/inode.c
+++ b/fs/exfat/inode.c
@@ -448,12 +448,11 @@ static void exfat_write_failed(struct address_space *mapping, loff_t to)
 
 static int exfat_write_begin(struct file *file, struct address_space *mapping,
 		loff_t pos, unsigned int len,
-		struct page **pagep, void **fsdata)
+		struct folio **foliop, void **fsdata)
 {
 	int ret;
 
-	*pagep = NULL;
-	ret = block_write_begin(mapping, pos, len, pagep, exfat_get_block);
+	ret = block_write_begin(mapping, pos, len, foliop, exfat_get_block);
 
 	if (ret < 0)
 		exfat_write_failed(mapping, pos+len);
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c
index aba41f6150e5..30f8201c155f 100644
--- a/fs/ext2/inode.c
+++ b/fs/ext2/inode.c
@@ -916,11 +916,11 @@ static void ext2_readahead(struct readahead_control *rac)
 
 static int
 ext2_write_begin(struct file *file, struct address_space *mapping,
-		loff_t pos, unsigned len, struct page **pagep, void **fsdata)
+		loff_t pos, unsigned len, struct folio **foliop, void **fsdata)
 {
 	int ret;
 
-	ret = block_write_begin(mapping, pos, len, pagep, ext2_get_block);
+	ret = block_write_begin(mapping, pos, len, foliop, ext2_get_block);
 	if (ret < 0)
 		ext2_write_failed(mapping, pos + len);
 	return ret;
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 08acd152261e..c3429b664b8d 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -3563,13 +3563,13 @@ int ext4_readpage_inline(struct inode *inode, struct folio *folio);
 extern int ext4_try_to_write_inline_data(struct address_space *mapping,
 					 struct inode *inode,
 					 loff_t pos, unsigned len,
-					 struct page **pagep);
+					 struct folio **foliop);
 int ext4_write_inline_data_end(struct inode *inode, loff_t pos, unsigned len,
 			       unsigned copied, struct folio *folio);
 extern int ext4_da_write_inline_data_begin(struct address_space *mapping,
 					   struct inode *inode,
 					   loff_t pos, unsigned len,
-					   struct page **pagep,
+					   struct folio **foliop,
 					   void **fsdata);
 extern int ext4_try_add_inline_entry(handle_t *handle,
 				     struct ext4_filename *fname,
diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
index e7a09a99837b..b7ea9cb4c398 100644
--- a/fs/ext4/inline.c
+++ b/fs/ext4/inline.c
@@ -660,7 +660,7 @@ static int ext4_convert_inline_data_to_extent(struct address_space *mapping,
 int ext4_try_to_write_inline_data(struct address_space *mapping,
 				  struct inode *inode,
 				  loff_t pos, unsigned len,
-				  struct page **pagep)
+				  struct folio **foliop)
 {
 	int ret;
 	handle_t *handle;
@@ -708,7 +708,7 @@ int ext4_try_to_write_inline_data(struct address_space *mapping,
 		goto out;
 	}
 
-	*pagep = &folio->page;
+	*foliop = folio;
 	down_read(&EXT4_I(inode)->xattr_sem);
 	if (!ext4_has_inline_data(inode)) {
 		ret = 0;
@@ -891,7 +891,7 @@ static int ext4_da_convert_inline_data_to_extent(struct address_space *mapping,
 int ext4_da_write_inline_data_begin(struct address_space *mapping,
 				    struct inode *inode,
 				    loff_t pos, unsigned len,
-				    struct page **pagep,
+				    struct folio **foliop,
 				    void **fsdata)
 {
 	int ret;
@@ -954,7 +954,7 @@ int ext4_da_write_inline_data_begin(struct address_space *mapping,
 		goto out_release_page;
 
 	up_read(&EXT4_I(inode)->xattr_sem);
-	*pagep = &folio->page;
+	*foliop = folio;
 	brelse(iloc.bh);
 	return 1;
 out_release_page:
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index e19ac0a82bdc..90ef8ec5c59b 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -1145,7 +1145,7 @@ static int ext4_block_write_begin(struct folio *folio, loff_t pos, unsigned len,
  */
 static int ext4_write_begin(struct file *file, struct address_space *mapping,
 			    loff_t pos, unsigned len,
-			    struct page **pagep, void **fsdata)
+			    struct folio **foliop, void **fsdata)
 {
 	struct inode *inode = mapping->host;
 	int ret, needed_blocks;
@@ -1170,7 +1170,7 @@ static int ext4_write_begin(struct file *file, struct address_space *mapping,
 
 	if (ext4_test_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA)) {
 		ret = ext4_try_to_write_inline_data(mapping, inode, pos, len,
-						    pagep);
+						    foliop);
 		if (ret < 0)
 			return ret;
 		if (ret == 1)
@@ -1270,7 +1270,7 @@ static int ext4_write_begin(struct file *file, struct address_space *mapping,
 		folio_put(folio);
 		return ret;
 	}
-	*pagep = &folio->page;
+	*foliop = folio;
 	return ret;
 }
 
@@ -2924,7 +2924,7 @@ static int ext4_nonda_switch(struct super_block *sb)
 
 static int ext4_da_write_begin(struct file *file, struct address_space *mapping,
 			       loff_t pos, unsigned len,
-			       struct page **pagep, void **fsdata)
+			       struct folio **foliop, void **fsdata)
 {
 	int ret, retries = 0;
 	struct folio *folio;
@@ -2939,14 +2939,14 @@ static int ext4_da_write_begin(struct file *file, struct address_space *mapping,
 	if (ext4_nonda_switch(inode->i_sb) || ext4_verity_in_progress(inode)) {
 		*fsdata = (void *)FALL_BACK_TO_NONDELALLOC;
 		return ext4_write_begin(file, mapping, pos,
-					len, pagep, fsdata);
+					len, foliop, fsdata);
 	}
 	*fsdata = (void *)0;
 	trace_ext4_da_write_begin(inode, pos, len);
 
 	if (ext4_test_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA)) {
 		ret = ext4_da_write_inline_data_begin(mapping, inode, pos, len,
-						      pagep, fsdata);
+						      foliop, fsdata);
 		if (ret < 0)
 			return ret;
 		if (ret == 1)
@@ -2981,7 +2981,7 @@ static int ext4_da_write_begin(struct file *file, struct address_space *mapping,
 		return ret;
 	}
 
-	*pagep = &folio->page;
+	*foliop = folio;
 	return ret;
 }
 
diff --git a/fs/ext4/verity.c b/fs/ext4/verity.c
index 86ef272296ab..d9203228ce97 100644
--- a/fs/ext4/verity.c
+++ b/fs/ext4/verity.c
@@ -76,17 +76,17 @@ static int pagecache_write(struct inode *inode, const void *buf, size_t count,
 	while (count) {
 		size_t n = min_t(size_t, count,
 				 PAGE_SIZE - offset_in_page(pos));
-		struct page *page;
+		struct folio *folio;
 		void *fsdata = NULL;
 		int res;
 
-		res = aops->write_begin(NULL, mapping, pos, n, &page, &fsdata);
+		res = aops->write_begin(NULL, mapping, pos, n, &folio, &fsdata);
 		if (res)
 			return res;
 
-		memcpy_to_page(page, offset_in_page(pos), buf, n);
+		memcpy_to_folio(folio, offset_in_folio(folio, pos), buf, n);
 
-		res = aops->write_end(NULL, mapping, pos, n, n, page_folio(page), fsdata);
+		res = aops->write_end(NULL, mapping, pos, n, n, folio, fsdata);
 		if (res < 0)
 			return res;
 		if (res != n)
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 4c32e2cfc403..5dfa0207ad8f 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -3552,7 +3552,7 @@ static int prepare_atomic_write_begin(struct f2fs_sb_info *sbi,
 }
 
 static int f2fs_write_begin(struct file *file, struct address_space *mapping,
-		loff_t pos, unsigned len, struct page **pagep, void **fsdata)
+		loff_t pos, unsigned len, struct folio **foliop, void **fsdata)
 {
 	struct inode *inode = mapping->host;
 	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
@@ -3584,18 +3584,20 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping,
 #ifdef CONFIG_F2FS_FS_COMPRESSION
 	if (f2fs_compressed_file(inode)) {
 		int ret;
+		struct page *page;
 
 		*fsdata = NULL;
 
 		if (len == PAGE_SIZE && !(f2fs_is_atomic_file(inode)))
 			goto repeat;
 
-		ret = f2fs_prepare_compress_overwrite(inode, pagep,
+		ret = f2fs_prepare_compress_overwrite(inode, &page,
 							index, fsdata);
 		if (ret < 0) {
 			err = ret;
 			goto fail;
 		} else if (ret) {
+			*foliop = page_folio(page);
 			return 0;
 		}
 	}
@@ -3615,7 +3617,7 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping,
 
 	/* TODO: cluster can be compressed due to race with .writepage */
 
-	*pagep = &folio->page;
+	*foliop = folio;
 
 	if (f2fs_is_atomic_file(inode))
 		err = prepare_atomic_write_begin(sbi, &folio->page, pos, len,
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index cfd38cd4f82c..176b5177c89d 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -2677,7 +2677,7 @@ static ssize_t f2fs_quota_write(struct super_block *sb, int type,
 	const struct address_space_operations *a_ops = mapping->a_ops;
 	int offset = off & (sb->s_blocksize - 1);
 	size_t towrite = len;
-	struct page *page;
+	struct folio *folio;
 	void *fsdata = NULL;
 	int err = 0;
 	int tocopy;
@@ -2687,7 +2687,7 @@ static ssize_t f2fs_quota_write(struct super_block *sb, int type,
 								towrite);
 retry:
 		err = a_ops->write_begin(NULL, mapping, off, tocopy,
-							&page, &fsdata);
+							&folio, &fsdata);
 		if (unlikely(err)) {
 			if (err == -ENOMEM) {
 				f2fs_io_schedule_timeout(DEFAULT_IO_TIMEOUT);
@@ -2697,10 +2697,10 @@ static ssize_t f2fs_quota_write(struct super_block *sb, int type,
 			break;
 		}
 
-		memcpy_to_page(page, offset, data, tocopy);
+		memcpy_to_folio(folio, offset_in_folio(folio, off), data, tocopy);
 
 		a_ops->write_end(NULL, mapping, off, tocopy, tocopy,
-						page_folio(page), fsdata);
+						folio, fsdata);
 		offset = 0;
 		towrite -= tocopy;
 		off += tocopy;
diff --git a/fs/f2fs/verity.c b/fs/f2fs/verity.c
index 486512144bf1..84a33fe49bed 100644
--- a/fs/f2fs/verity.c
+++ b/fs/f2fs/verity.c
@@ -80,17 +80,17 @@ static int pagecache_write(struct inode *inode, const void *buf, size_t count,
 	while (count) {
 		size_t n = min_t(size_t, count,
 				 PAGE_SIZE - offset_in_page(pos));
-		struct page *page;
+		struct folio *folio;
 		void *fsdata = NULL;
 		int res;
 
-		res = aops->write_begin(NULL, mapping, pos, n, &page, &fsdata);
+		res = aops->write_begin(NULL, mapping, pos, n, &folio, &fsdata);
 		if (res)
 			return res;
 
-		memcpy_to_page(page, offset_in_page(pos), buf, n);
+		memcpy_to_folio(folio, offset_in_folio(folio, pos), buf, n);
 
-		res = aops->write_end(NULL, mapping, pos, n, n, page_folio(page), fsdata);
+		res = aops->write_end(NULL, mapping, pos, n, n, folio, fsdata);
 		if (res < 0)
 			return res;
 		if (res != n)
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index 8ed02b17d591..75722bbd6b5f 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -221,13 +221,12 @@ static void fat_write_failed(struct address_space *mapping, loff_t to)
 
 static int fat_write_begin(struct file *file, struct address_space *mapping,
 			loff_t pos, unsigned len,
-			struct page **pagep, void **fsdata)
+			struct folio **foliop, void **fsdata)
 {
 	int err;
 
-	*pagep = NULL;
 	err = cont_write_begin(file, mapping, pos, len,
-				pagep, fsdata, fat_get_block,
+				foliop, fsdata, fat_get_block,
 				&MSDOS_I(mapping->host)->mmu_private);
 	if (err < 0)
 		fat_write_failed(mapping, pos + len);
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index a5cd6e4f9b2b..bc49b2eeadf3 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -2387,7 +2387,7 @@ static int fuse_writepages(struct address_space *mapping,
  * but how to implement it without killing performance need more thinking.
  */
 static int fuse_write_begin(struct file *file, struct address_space *mapping,
-		loff_t pos, unsigned len, struct page **pagep, void **fsdata)
+		loff_t pos, unsigned len, struct folio **foliop, void **fsdata)
 {
 	pgoff_t index = pos >> PAGE_SHIFT;
 	struct fuse_conn *fc = get_fuse_conn(file_inode(file));
@@ -2421,7 +2421,7 @@ static int fuse_write_begin(struct file *file, struct address_space *mapping,
 	if (err)
 		goto cleanup;
 success:
-	*pagep = &folio->page;
+	*foliop = folio;
 	return 0;
 
 cleanup:
diff --git a/fs/hfs/extent.c b/fs/hfs/extent.c
index 30512dbb79f0..4a0ce131e233 100644
--- a/fs/hfs/extent.c
+++ b/fs/hfs/extent.c
@@ -487,15 +487,15 @@ void hfs_file_truncate(struct inode *inode)
 	if (inode->i_size > HFS_I(inode)->phys_size) {
 		struct address_space *mapping = inode->i_mapping;
 		void *fsdata = NULL;
-		struct page *page;
+		struct folio *folio;
 
 		/* XXX: Can use generic_cont_expand? */
 		size = inode->i_size - 1;
-		res = hfs_write_begin(NULL, mapping, size + 1, 0, &page,
+		res = hfs_write_begin(NULL, mapping, size + 1, 0, &folio,
 				&fsdata);
 		if (!res) {
 			res = generic_write_end(NULL, mapping, size + 1, 0, 0,
-					page_folio(page), fsdata);
+					folio, fsdata);
 		}
 		if (res)
 			inode->i_size = HFS_I(inode)->phys_size;
diff --git a/fs/hfs/hfs_fs.h b/fs/hfs/hfs_fs.h
index b5a6ad5df357..a0c7cb0f79fc 100644
--- a/fs/hfs/hfs_fs.h
+++ b/fs/hfs/hfs_fs.h
@@ -202,7 +202,7 @@ extern const struct address_space_operations hfs_aops;
 extern const struct address_space_operations hfs_btree_aops;
 
 int hfs_write_begin(struct file *file, struct address_space *mapping,
-		loff_t pos, unsigned len, struct page **pagep, void **fsdata);
+		loff_t pos, unsigned len, struct folio **foliop, void **fsdata);
 extern struct inode *hfs_new_inode(struct inode *, const struct qstr *, umode_t);
 extern void hfs_inode_write_fork(struct inode *, struct hfs_extent *, __be32 *, __be32 *);
 extern int hfs_write_inode(struct inode *, struct writeback_control *);
diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c
index 744e10b46904..a81ce7a740b9 100644
--- a/fs/hfs/inode.c
+++ b/fs/hfs/inode.c
@@ -45,12 +45,11 @@ static void hfs_write_failed(struct address_space *mapping, loff_t to)
 }
 
 int hfs_write_begin(struct file *file, struct address_space *mapping,
-		loff_t pos, unsigned len, struct page **pagep, void **fsdata)
+		loff_t pos, unsigned len, struct folio **foliop, void **fsdata)
 {
 	int ret;
 
-	*pagep = NULL;
-	ret = cont_write_begin(file, mapping, pos, len, pagep, fsdata,
+	ret = cont_write_begin(file, mapping, pos, len, foliop, fsdata,
 				hfs_get_block,
 				&HFS_I(mapping->host)->phys_size);
 	if (unlikely(ret))
diff --git a/fs/hfsplus/extents.c b/fs/hfsplus/extents.c
index 776c0ea722cb..a6d61685ae79 100644
--- a/fs/hfsplus/extents.c
+++ b/fs/hfsplus/extents.c
@@ -554,16 +554,16 @@ void hfsplus_file_truncate(struct inode *inode)
 
 	if (inode->i_size > hip->phys_size) {
 		struct address_space *mapping = inode->i_mapping;
-		struct page *page;
+		struct folio *folio;
 		void *fsdata = NULL;
 		loff_t size = inode->i_size;
 
 		res = hfsplus_write_begin(NULL, mapping, size, 0,
-					  &page, &fsdata);
+					  &folio, &fsdata);
 		if (res)
 			return;
 		res = generic_write_end(NULL, mapping, size, 0, 0,
-					page_folio(page), fsdata);
+					folio, fsdata);
 		if (res < 0)
 			return;
 		mark_inode_dirty(inode);
diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h
index 9e78f181c24f..59ce81dca73f 100644
--- a/fs/hfsplus/hfsplus_fs.h
+++ b/fs/hfsplus/hfsplus_fs.h
@@ -472,7 +472,7 @@ extern const struct address_space_operations hfsplus_btree_aops;
 extern const struct dentry_operations hfsplus_dentry_operations;
 
 int hfsplus_write_begin(struct file *file, struct address_space *mapping,
-		loff_t pos, unsigned len, struct page **pagep, void **fsdata);
+		loff_t pos, unsigned len, struct folio **foliop, void **fsdata);
 struct inode *hfsplus_new_inode(struct super_block *sb, struct inode *dir,
 				umode_t mode);
 void hfsplus_delete_inode(struct inode *inode);
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
index 3d326926c195..f331e9574217 100644
--- a/fs/hfsplus/inode.c
+++ b/fs/hfsplus/inode.c
@@ -39,12 +39,11 @@ static void hfsplus_write_failed(struct address_space *mapping, loff_t to)
 }
 
 int hfsplus_write_begin(struct file *file, struct address_space *mapping,
-		loff_t pos, unsigned len, struct page **pagep, void **fsdata)
+		loff_t pos, unsigned len, struct folio **foliop, void **fsdata)
 {
 	int ret;
 
-	*pagep = NULL;
-	ret = cont_write_begin(file, mapping, pos, len, pagep, fsdata,
+	ret = cont_write_begin(file, mapping, pos, len, foliop, fsdata,
 				hfsplus_get_block,
 				&HFSPLUS_I(mapping->host)->phys_size);
 	if (unlikely(ret))
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
index 6452431231ab..5acedbaa9296 100644
--- a/fs/hostfs/hostfs_kern.c
+++ b/fs/hostfs/hostfs_kern.c
@@ -464,12 +464,13 @@ static int hostfs_read_folio(struct file *file, struct folio *folio)
 
 static int hostfs_write_begin(struct file *file, struct address_space *mapping,
 			      loff_t pos, unsigned len,
-			      struct page **pagep, void **fsdata)
+			      struct folio **foliop, void **fsdata)
 {
 	pgoff_t index = pos >> PAGE_SHIFT;
 
-	*pagep = grab_cache_page_write_begin(mapping, index);
-	if (!*pagep)
+	*foliop = __filemap_get_folio(mapping, index, FGP_WRITEBEGIN,
+			mapping_gfp_mask(mapping));
+	if (!*foliop)
 		return -ENOMEM;
 	return 0;
 }
diff --git a/fs/hpfs/file.c b/fs/hpfs/file.c
index 11e2d9e612ac..449a3fc1b8d9 100644
--- a/fs/hpfs/file.c
+++ b/fs/hpfs/file.c
@@ -190,12 +190,11 @@ static void hpfs_write_failed(struct address_space *mapping, loff_t to)
 
 static int hpfs_write_begin(struct file *file, struct address_space *mapping,
 			loff_t pos, unsigned len,
-			struct page **pagep, void **fsdata)
+			struct folio **foliop, void **fsdata)
 {
 	int ret;
 
-	*pagep = NULL;
-	ret = cont_write_begin(file, mapping, pos, len, pagep, fsdata,
+	ret = cont_write_begin(file, mapping, pos, len, foliop, fsdata,
 				hpfs_get_block,
 				&hpfs_i(mapping->host)->mmu_private);
 	if (unlikely(ret))
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index b7a30055e6f4..5cf327337e22 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -388,7 +388,7 @@ static ssize_t hugetlbfs_read_iter(struct kiocb *iocb, struct iov_iter *to)
 static int hugetlbfs_write_begin(struct file *file,
 			struct address_space *mapping,
 			loff_t pos, unsigned len,
-			struct page **pagep, void **fsdata)
+			struct folio **foliop, void **fsdata)
 {
 	return -EINVAL;
 }
diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c
index b6fe1f1e8ea9..ada572c466f8 100644
--- a/fs/jffs2/file.c
+++ b/fs/jffs2/file.c
@@ -26,7 +26,7 @@ static int jffs2_write_end(struct file *filp, struct address_space *mapping,
 			struct folio *folio, void *fsdata);
 static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
 			loff_t pos, unsigned len,
-			struct page **pagep, void **fsdata);
+			struct folio **foliop, void **fsdata);
 static int jffs2_read_folio(struct file *filp, struct folio *folio);
 
 int jffs2_fsync(struct file *filp, loff_t start, loff_t end, int datasync)
@@ -125,7 +125,7 @@ static int jffs2_read_folio(struct file *file, struct folio *folio)
 
 static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
 			loff_t pos, unsigned len,
-			struct page **pagep, void **fsdata)
+			struct folio **foliop, void **fsdata)
 {
 	struct folio *folio;
 	struct inode *inode = mapping->host;
@@ -212,7 +212,7 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
 		ret = PTR_ERR(folio);
 		goto release_sem;
 	}
-	*pagep = &folio->page;
+	*foliop = folio;
 
 	/*
 	 * Read in the folio if it wasn't already present. Cannot optimize away
diff --git a/fs/jfs/inode.c b/fs/jfs/inode.c
index d63494182548..07cfdc440596 100644
--- a/fs/jfs/inode.c
+++ b/fs/jfs/inode.c
@@ -292,11 +292,11 @@ static void jfs_write_failed(struct address_space *mapping, loff_t to)
 
 static int jfs_write_begin(struct file *file, struct address_space *mapping,
 				loff_t pos, unsigned len,
-				struct page **pagep, void **fsdata)
+				struct folio **foliop, void **fsdata)
 {
 	int ret;
 
-	ret = block_write_begin(mapping, pos, len, pagep, jfs_get_block);
+	ret = block_write_begin(mapping, pos, len, foliop, jfs_get_block);
 	if (unlikely(ret))
 		jfs_write_failed(mapping, pos + len);
 
diff --git a/fs/libfs.c b/fs/libfs.c
index 4581be1d5b32..1a776edb39de 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -901,7 +901,7 @@ static int simple_read_folio(struct file *file, struct folio *folio)
 
 int simple_write_begin(struct file *file, struct address_space *mapping,
 			loff_t pos, unsigned len,
-			struct page **pagep, void **fsdata)
+			struct folio **foliop, void **fsdata)
 {
 	struct folio *folio;
 
@@ -910,7 +910,7 @@ int simple_write_begin(struct file *file, struct address_space *mapping,
 	if (IS_ERR(folio))
 		return PTR_ERR(folio);
 
-	*pagep = &folio->page;
+	*foliop = folio;
 
 	if (!folio_test_uptodate(folio) && (len != folio_size(folio))) {
 		size_t from = offset_in_folio(folio, pos);
diff --git a/fs/minix/inode.c b/fs/minix/inode.c
index 0002337977e0..abb190c46c04 100644
--- a/fs/minix/inode.c
+++ b/fs/minix/inode.c
@@ -444,11 +444,11 @@ static void minix_write_failed(struct address_space *mapping, loff_t to)
 
 static int minix_write_begin(struct file *file, struct address_space *mapping,
 			loff_t pos, unsigned len,
-			struct page **pagep, void **fsdata)
+			struct folio **foliop, void **fsdata)
 {
 	int ret;
 
-	ret = block_write_begin(mapping, pos, len, pagep, minix_get_block);
+	ret = block_write_begin(mapping, pos, len, foliop, minix_get_block);
 	if (unlikely(ret))
 		minix_write_failed(mapping, pos + len);
 
diff --git a/fs/namei.c b/fs/namei.c
index c65c03bc3703..d813b8672317 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -5308,7 +5308,7 @@ int page_symlink(struct inode *inode, const char *symname, int len)
 	struct address_space *mapping = inode->i_mapping;
 	const struct address_space_operations *aops = mapping->a_ops;
 	bool nofs = !mapping_gfp_constraint(mapping, __GFP_FS);
-	struct page *page;
+	struct folio *folio;
 	void *fsdata = NULL;
 	int err;
 	unsigned int flags;
@@ -5316,16 +5316,16 @@ int page_symlink(struct inode *inode, const char *symname, int len)
 retry:
 	if (nofs)
 		flags = memalloc_nofs_save();
-	err = aops->write_begin(NULL, mapping, 0, len-1, &page, &fsdata);
+	err = aops->write_begin(NULL, mapping, 0, len-1, &folio, &fsdata);
 	if (nofs)
 		memalloc_nofs_restore(flags);
 	if (err)
 		goto fail;
 
-	memcpy(page_address(page), symname, len-1);
+	memcpy(folio_address(folio), symname, len - 1);
 
-	err = aops->write_end(NULL, mapping, 0, len-1, len-1,
-						page_folio(page), fsdata);
+	err = aops->write_end(NULL, mapping, 0, len - 1, len - 1,
+						folio, fsdata);
 	if (err < 0)
 		goto fail;
 	if (err < len-1)
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index fe583dbebe54..6800ee92d742 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -336,7 +336,7 @@ static bool nfs_want_read_modify_write(struct file *file, struct folio *folio,
  * increment the page use counts until he is done with the page.
  */
 static int nfs_write_begin(struct file *file, struct address_space *mapping,
-			   loff_t pos, unsigned len, struct page **pagep,
+			   loff_t pos, unsigned len, struct folio **foliop,
 			   void **fsdata)
 {
 	fgf_t fgp = FGP_WRITEBEGIN;
@@ -353,7 +353,7 @@ static int nfs_write_begin(struct file *file, struct address_space *mapping,
 				    mapping_gfp_mask(mapping));
 	if (IS_ERR(folio))
 		return PTR_ERR(folio);
-	*pagep = &folio->page;
+	*foliop = folio;
 
 	ret = nfs_flush_incompatible(file, folio);
 	if (ret) {
diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c
index 25841b75415a..8661f452dba6 100644
--- a/fs/nilfs2/inode.c
+++ b/fs/nilfs2/inode.c
@@ -250,7 +250,7 @@ void nilfs_write_failed(struct address_space *mapping, loff_t to)
 
 static int nilfs_write_begin(struct file *file, struct address_space *mapping,
 			     loff_t pos, unsigned len,
-			     struct page **pagep, void **fsdata)
+			     struct folio **foliop, void **fsdata)
 
 {
 	struct inode *inode = mapping->host;
@@ -259,7 +259,7 @@ static int nilfs_write_begin(struct file *file, struct address_space *mapping,
 	if (unlikely(err))
 		return err;
 
-	err = block_write_begin(mapping, pos, len, pagep, nilfs_get_block);
+	err = block_write_begin(mapping, pos, len, foliop, nilfs_get_block);
 	if (unlikely(err)) {
 		nilfs_write_failed(mapping, pos + len);
 		nilfs_transaction_abort(inode->i_sb);
diff --git a/fs/nilfs2/recovery.c b/fs/nilfs2/recovery.c
index 40c5dfbc9d41..c2e60a6bd060 100644
--- a/fs/nilfs2/recovery.c
+++ b/fs/nilfs2/recovery.c
@@ -498,7 +498,6 @@ static int nilfs_recover_dsync_blocks(struct the_nilfs *nilfs,
 	struct inode *inode;
 	struct nilfs_recovery_block *rb, *n;
 	unsigned int blocksize = nilfs->ns_blocksize;
-	struct page *page;
 	struct folio *folio;
 	loff_t pos;
 	int err = 0, err2 = 0;
@@ -513,7 +512,7 @@ static int nilfs_recover_dsync_blocks(struct the_nilfs *nilfs,
 
 		pos = rb->blkoff << inode->i_blkbits;
 		err = block_write_begin(inode->i_mapping, pos, blocksize,
-					&page, nilfs_get_block);
+					&folio, nilfs_get_block);
 		if (unlikely(err)) {
 			loff_t isize = inode->i_size;
 
@@ -523,8 +522,7 @@ static int nilfs_recover_dsync_blocks(struct the_nilfs *nilfs,
 			goto failed_inode;
 		}
 
-		folio = page_folio(page);
-		err = nilfs_recovery_copy_block(nilfs, rb, pos, page);
+		err = nilfs_recovery_copy_block(nilfs, rb, pos, &folio->page);
 		if (unlikely(err))
 			goto failed_page;
 
diff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c
index 88a7d81cf2ba..6202895a4542 100644
--- a/fs/ntfs3/file.c
+++ b/fs/ntfs3/file.c
@@ -182,7 +182,7 @@ static int ntfs_extend_initialized_size(struct file *file,
 
 	for (;;) {
 		u32 zerofrom, len;
-		struct page *page;
+		struct folio *folio;
 		u8 bits;
 		CLST vcn, lcn, clen;
 
@@ -208,14 +208,13 @@ static int ntfs_extend_initialized_size(struct file *file,
 		if (pos + len > new_valid)
 			len = new_valid - pos;
 
-		err = ntfs_write_begin(file, mapping, pos, len, &page, NULL);
+		err = ntfs_write_begin(file, mapping, pos, len, &folio, NULL);
 		if (err)
 			goto out;
 
-		zero_user_segment(page, zerofrom, PAGE_SIZE);
+		folio_zero_range(folio, zerofrom, folio_size(folio));
 
-		/* This function in any case puts page. */
-		err = ntfs_write_end(file, mapping, pos, len, len, page_folio(page), NULL);
+		err = ntfs_write_end(file, mapping, pos, len, len, folio, NULL);
 		if (err < 0)
 			goto out;
 		pos += len;
diff --git a/fs/ntfs3/inode.c b/fs/ntfs3/inode.c
index 9efd3f7c59d6..f672072e6bd4 100644
--- a/fs/ntfs3/inode.c
+++ b/fs/ntfs3/inode.c
@@ -901,7 +901,7 @@ static int ntfs_get_block_write_begin(struct inode *inode, sector_t vbn,
 }
 
 int ntfs_write_begin(struct file *file, struct address_space *mapping,
-		     loff_t pos, u32 len, struct page **pagep, void **fsdata)
+		     loff_t pos, u32 len, struct folio **foliop, void **fsdata)
 {
 	int err;
 	struct inode *inode = mapping->host;
@@ -910,7 +910,6 @@ int ntfs_write_begin(struct file *file, struct address_space *mapping,
 	if (unlikely(ntfs3_forced_shutdown(inode->i_sb)))
 		return -EIO;
 
-	*pagep = NULL;
 	if (is_resident(ni)) {
 		struct folio *folio = __filemap_get_folio(
 			mapping, pos >> PAGE_SHIFT, FGP_WRITEBEGIN,
@@ -926,7 +925,7 @@ int ntfs_write_begin(struct file *file, struct address_space *mapping,
 		ni_unlock(ni);
 
 		if (!err) {
-			*pagep = &folio->page;
+			*foliop = folio;
 			goto out;
 		}
 		folio_unlock(folio);
@@ -936,7 +935,7 @@ int ntfs_write_begin(struct file *file, struct address_space *mapping,
 			goto out;
 	}
 
-	err = block_write_begin(mapping, pos, len, pagep,
+	err = block_write_begin(mapping, pos, len, foliop,
 				ntfs_get_block_write_begin);
 
 out:
diff --git a/fs/ntfs3/ntfs_fs.h b/fs/ntfs3/ntfs_fs.h
index 53517281f26b..584f814715f4 100644
--- a/fs/ntfs3/ntfs_fs.h
+++ b/fs/ntfs3/ntfs_fs.h
@@ -711,7 +711,7 @@ int ntfs_set_size(struct inode *inode, u64 new_size);
 int ntfs_get_block(struct inode *inode, sector_t vbn,
 		   struct buffer_head *bh_result, int create);
 int ntfs_write_begin(struct file *file, struct address_space *mapping,
-		     loff_t pos, u32 len, struct page **pagep, void **fsdata);
+		     loff_t pos, u32 len, struct folio **foliop, void **fsdata);
 int ntfs_write_end(struct file *file, struct address_space *mapping, loff_t pos,
 		   u32 len, u32 copied, struct folio *folio, void *fsdata);
 int ntfs3_write_inode(struct inode *inode, struct writeback_control *wbc);
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c
index 9d8aa417e8da..d6c985cc6353 100644
--- a/fs/ocfs2/aops.c
+++ b/fs/ocfs2/aops.c
@@ -1643,7 +1643,7 @@ static int ocfs2_zero_tail(struct inode *inode, struct buffer_head *di_bh,
 
 int ocfs2_write_begin_nolock(struct address_space *mapping,
 			     loff_t pos, unsigned len, ocfs2_write_type_t type,
-			     struct page **pagep, void **fsdata,
+			     struct folio **foliop, void **fsdata,
 			     struct buffer_head *di_bh, struct page *mmap_page)
 {
 	int ret, cluster_of_pages, credits = OCFS2_INODE_UPDATE_CREDITS;
@@ -1826,8 +1826,8 @@ int ocfs2_write_begin_nolock(struct address_space *mapping,
 		ocfs2_free_alloc_context(meta_ac);
 
 success:
-	if (pagep)
-		*pagep = wc->w_target_page;
+	if (foliop)
+		*foliop = page_folio(wc->w_target_page);
 	*fsdata = wc;
 	return 0;
 out_quota:
@@ -1879,7 +1879,7 @@ int ocfs2_write_begin_nolock(struct address_space *mapping,
 
 static int ocfs2_write_begin(struct file *file, struct address_space *mapping,
 			     loff_t pos, unsigned len,
-			     struct page **pagep, void **fsdata)
+			     struct folio **foliop, void **fsdata)
 {
 	int ret;
 	struct buffer_head *di_bh = NULL;
@@ -1901,7 +1901,7 @@ static int ocfs2_write_begin(struct file *file, struct address_space *mapping,
 	down_write(&OCFS2_I(inode)->ip_alloc_sem);
 
 	ret = ocfs2_write_begin_nolock(mapping, pos, len, OCFS2_WRITE_BUFFER,
-				       pagep, fsdata, di_bh, NULL);
+				       foliop, fsdata, di_bh, NULL);
 	if (ret) {
 		mlog_errno(ret);
 		goto out_fail;
diff --git a/fs/ocfs2/aops.h b/fs/ocfs2/aops.h
index 3a520117fa59..45db1781ea73 100644
--- a/fs/ocfs2/aops.h
+++ b/fs/ocfs2/aops.h
@@ -38,7 +38,7 @@ typedef enum {
 
 int ocfs2_write_begin_nolock(struct address_space *mapping,
 			     loff_t pos, unsigned len, ocfs2_write_type_t type,
-			     struct page **pagep, void **fsdata,
+			     struct folio **foliop, void **fsdata,
 			     struct buffer_head *di_bh, struct page *mmap_page);
 
 int ocfs2_read_inline_data(struct inode *inode, struct page *page,
diff --git a/fs/ocfs2/mmap.c b/fs/ocfs2/mmap.c
index 1834f26522ed..6ef4cb045ccd 100644
--- a/fs/ocfs2/mmap.c
+++ b/fs/ocfs2/mmap.c
@@ -53,7 +53,7 @@ static vm_fault_t __ocfs2_page_mkwrite(struct file *file,
 	loff_t pos = page_offset(page);
 	unsigned int len = PAGE_SIZE;
 	pgoff_t last_index;
-	struct page *locked_page = NULL;
+	struct folio *locked_folio = NULL;
 	void *fsdata;
 	loff_t size = i_size_read(inode);
 
@@ -91,7 +91,7 @@ static vm_fault_t __ocfs2_page_mkwrite(struct file *file,
 		len = ((size - 1) & ~PAGE_MASK) + 1;
 
 	err = ocfs2_write_begin_nolock(mapping, pos, len, OCFS2_WRITE_MMAP,
-				       &locked_page, &fsdata, di_bh, page);
+				       &locked_folio, &fsdata, di_bh, page);
 	if (err) {
 		if (err != -ENOSPC)
 			mlog_errno(err);
@@ -99,7 +99,7 @@ static vm_fault_t __ocfs2_page_mkwrite(struct file *file,
 		goto out;
 	}
 
-	if (!locked_page) {
+	if (!locked_folio) {
 		ret = VM_FAULT_NOPAGE;
 		goto out;
 	}
diff --git a/fs/omfs/file.c b/fs/omfs/file.c
index 6b580b9da8e3..98358d405b6a 100644
--- a/fs/omfs/file.c
+++ b/fs/omfs/file.c
@@ -312,11 +312,11 @@ static void omfs_write_failed(struct address_space *mapping, loff_t to)
 
 static int omfs_write_begin(struct file *file, struct address_space *mapping,
 			loff_t pos, unsigned len,
-			struct page **pagep, void **fsdata)
+			struct folio **foliop, void **fsdata)
 {
 	int ret;
 
-	ret = block_write_begin(mapping, pos, len, pagep, omfs_get_block);
+	ret = block_write_begin(mapping, pos, len, foliop, omfs_get_block);
 	if (unlikely(ret))
 		omfs_write_failed(mapping, pos + len);
 
diff --git a/fs/orangefs/inode.c b/fs/orangefs/inode.c
index 69b507a611f8..aae6d2b8767d 100644
--- a/fs/orangefs/inode.c
+++ b/fs/orangefs/inode.c
@@ -309,7 +309,7 @@ static int orangefs_read_folio(struct file *file, struct folio *folio)
 
 static int orangefs_write_begin(struct file *file,
 		struct address_space *mapping, loff_t pos, unsigned len,
-		struct page **pagep, void **fsdata)
+		struct folio **foliop, void **fsdata)
 {
 	struct orangefs_write_range *wr;
 	struct folio *folio;
@@ -320,7 +320,7 @@ static int orangefs_write_begin(struct file *file,
 	if (IS_ERR(folio))
 		return PTR_ERR(folio);
 
-	*pagep = &folio->page;
+	*foliop = folio;
 
 	if (folio_test_dirty(folio) && !folio_test_private(folio)) {
 		/*
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index f4b9db4b4df2..ea23872ba24f 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -2735,7 +2735,7 @@ static void reiserfs_truncate_failed_write(struct inode *inode)
 static int reiserfs_write_begin(struct file *file,
 				struct address_space *mapping,
 				loff_t pos, unsigned len,
-				struct page **pagep, void **fsdata)
+				struct folio **foliop, void **fsdata)
 {
 	struct inode *inode;
 	struct folio *folio;
@@ -2749,7 +2749,7 @@ static int reiserfs_write_begin(struct file *file,
 			mapping_gfp_mask(mapping));
 	if (IS_ERR(folio))
 		return PTR_ERR(folio);
-	*pagep = &folio->page;
+	*foliop = folio;
 
 	reiserfs_wait_on_write_block(inode->i_sb);
 	fix_tail_page_for_writing(&folio->page);
diff --git a/fs/sysv/itree.c b/fs/sysv/itree.c
index c8511e286673..8864438817a6 100644
--- a/fs/sysv/itree.c
+++ b/fs/sysv/itree.c
@@ -483,11 +483,11 @@ static void sysv_write_failed(struct address_space *mapping, loff_t to)
 
 static int sysv_write_begin(struct file *file, struct address_space *mapping,
 			loff_t pos, unsigned len,
-			struct page **pagep, void **fsdata)
+			struct folio **foliop, void **fsdata)
 {
 	int ret;
 
-	ret = block_write_begin(mapping, pos, len, pagep, get_block);
+	ret = block_write_begin(mapping, pos, len, foliop, get_block);
 	if (unlikely(ret))
 		sysv_write_failed(mapping, pos + len);
 
diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c
index baa3eecc32fe..5130123005e4 100644
--- a/fs/ubifs/file.c
+++ b/fs/ubifs/file.c
@@ -211,7 +211,7 @@ static void release_existing_page_budget(struct ubifs_info *c)
 }
 
 static int write_begin_slow(struct address_space *mapping,
-			    loff_t pos, unsigned len, struct page **pagep)
+			    loff_t pos, unsigned len, struct folio **foliop)
 {
 	struct inode *inode = mapping->host;
 	struct ubifs_info *c = inode->i_sb->s_fs_info;
@@ -298,7 +298,7 @@ static int write_begin_slow(struct address_space *mapping,
 			ubifs_release_dirty_inode_budget(c, ui);
 	}
 
-	*pagep = &folio->page;
+	*foliop = folio;
 	return 0;
 }
 
@@ -414,7 +414,7 @@ static int allocate_budget(struct ubifs_info *c, struct folio *folio,
  */
 static int ubifs_write_begin(struct file *file, struct address_space *mapping,
 			     loff_t pos, unsigned len,
-			     struct page **pagep, void **fsdata)
+			     struct folio **foliop, void **fsdata)
 {
 	struct inode *inode = mapping->host;
 	struct ubifs_info *c = inode->i_sb->s_fs_info;
@@ -483,7 +483,7 @@ static int ubifs_write_begin(struct file *file, struct address_space *mapping,
 		folio_unlock(folio);
 		folio_put(folio);
 
-		return write_begin_slow(mapping, pos, len, pagep);
+		return write_begin_slow(mapping, pos, len, foliop);
 	}
 
 	/*
@@ -492,7 +492,7 @@ static int ubifs_write_begin(struct file *file, struct address_space *mapping,
 	 * with @ui->ui_mutex locked if we are appending pages, and unlocked
 	 * otherwise. This is an optimization (slightly hacky though).
 	 */
-	*pagep = &folio->page;
+	*foliop = folio;
 	return 0;
 }
 
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index fdf024e0b772..eaee57b91c6c 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -246,14 +246,14 @@ static void udf_readahead(struct readahead_control *rac)
 
 static int udf_write_begin(struct file *file, struct address_space *mapping,
 			   loff_t pos, unsigned len,
-			   struct page **pagep, void **fsdata)
+			   struct folio **foliop, void **fsdata)
 {
 	struct udf_inode_info *iinfo = UDF_I(file_inode(file));
 	struct folio *folio;
 	int ret;
 
 	if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {
-		ret = block_write_begin(mapping, pos, len, pagep,
+		ret = block_write_begin(mapping, pos, len, foliop,
 					udf_get_block);
 		if (unlikely(ret))
 			udf_write_failed(mapping, pos + len);
@@ -265,7 +265,7 @@ static int udf_write_begin(struct file *file, struct address_space *mapping,
 			mapping_gfp_mask(mapping));
 	if (IS_ERR(folio))
 		return PTR_ERR(folio);
-	*pagep = &folio->page;
+	*foliop = folio;
 	if (!folio_test_uptodate(folio))
 		udf_adinicb_read_folio(folio);
 	return 0;
diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c
index 69adb198c634..f43461652d9f 100644
--- a/fs/ufs/inode.c
+++ b/fs/ufs/inode.c
@@ -498,11 +498,11 @@ static void ufs_write_failed(struct address_space *mapping, loff_t to)
 
 static int ufs_write_begin(struct file *file, struct address_space *mapping,
 			loff_t pos, unsigned len,
-			struct page **pagep, void **fsdata)
+			struct folio **foliop, void **fsdata)
 {
 	int ret;
 
-	ret = block_write_begin(mapping, pos, len, pagep, ufs_getfrag_block);
+	ret = block_write_begin(mapping, pos, len, foliop, ufs_getfrag_block);
 	if (unlikely(ret))
 		ufs_write_failed(mapping, pos + len);
 
diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h
index 165e859664a5..254563a2a9de 100644
--- a/include/linux/buffer_head.h
+++ b/include/linux/buffer_head.h
@@ -258,7 +258,7 @@ int __block_write_full_folio(struct inode *inode, struct folio *folio,
 int block_read_full_folio(struct folio *, get_block_t *);
 bool block_is_partially_uptodate(struct folio *, size_t from, size_t count);
 int block_write_begin(struct address_space *mapping, loff_t pos, unsigned len,
-		struct page **pagep, get_block_t *get_block);
+		struct folio **foliop, get_block_t *get_block);
 int __block_write_begin(struct page *page, loff_t pos, unsigned len,
 		get_block_t *get_block);
 int block_write_end(struct file *, struct address_space *,
@@ -269,7 +269,7 @@ int generic_write_end(struct file *, struct address_space *,
 				struct folio *, void *);
 void folio_zero_new_buffers(struct folio *folio, size_t from, size_t to);
 int cont_write_begin(struct file *, struct address_space *, loff_t,
-			unsigned, struct page **, void **,
+			unsigned, struct folio **, void **,
 			get_block_t *, loff_t *);
 int generic_cont_expand_simple(struct inode *inode, loff_t size);
 void block_commit_write(struct page *page, unsigned int from, unsigned int to);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 6ff85d72067b..34059e58aa92 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -408,7 +408,7 @@ struct address_space_operations {
 
 	int (*write_begin)(struct file *, struct address_space *mapping,
 				loff_t pos, unsigned len,
-				struct page **pagep, void **fsdata);
+				struct folio **foliop, void **fsdata);
 	int (*write_end)(struct file *, struct address_space *mapping,
 				loff_t pos, unsigned len, unsigned copied,
 				struct folio *folio, void *fsdata);
@@ -3331,7 +3331,7 @@ extern ssize_t noop_direct_IO(struct kiocb *iocb, struct iov_iter *iter);
 extern int simple_empty(struct dentry *);
 extern int simple_write_begin(struct file *file, struct address_space *mapping,
 			loff_t pos, unsigned len,
-			struct page **pagep, void **fsdata);
+			struct folio **foliop, void **fsdata);
 extern const struct address_space_operations ram_aops;
 extern int always_delete_dentry(const struct dentry *);
 extern struct inode *alloc_anon_inode(struct super_block *);
diff --git a/mm/filemap.c b/mm/filemap.c
index fab6b0c3044e..29fec1fccd0a 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -3987,7 +3987,6 @@ ssize_t generic_perform_write(struct kiocb *iocb, struct iov_iter *i)
 	ssize_t written = 0;
 
 	do {
-		struct page *page;
 		struct folio *folio;
 		size_t offset;		/* Offset into folio */
 		size_t bytes;		/* Bytes to write to folio */
@@ -4017,11 +4016,10 @@ ssize_t generic_perform_write(struct kiocb *iocb, struct iov_iter *i)
 		}
 
 		status = a_ops->write_begin(file, mapping, pos, bytes,
-						&page, &fsdata);
+						&folio, &fsdata);
 		if (unlikely(status < 0))
 			break;
 
-		folio = page_folio(page);
 		offset = offset_in_folio(folio, pos);
 		if (bytes > folio_size(folio) - offset)
 			bytes = folio_size(folio) - offset;
diff --git a/mm/shmem.c b/mm/shmem.c
index 1116f147d788..a8618eeed77a 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -2882,7 +2882,7 @@ static const struct inode_operations shmem_short_symlink_operations;
 static int
 shmem_write_begin(struct file *file, struct address_space *mapping,
 			loff_t pos, unsigned len,
-			struct page **pagep, void **fsdata)
+			struct folio **foliop, void **fsdata)
 {
 	struct inode *inode = mapping->host;
 	struct shmem_inode_info *info = SHMEM_I(inode);
@@ -2903,14 +2903,13 @@ shmem_write_begin(struct file *file, struct address_space *mapping,
 	if (ret)
 		return ret;
 
-	*pagep = folio_file_page(folio, index);
-	if (PageHWPoison(*pagep)) {
+	if (folio_test_has_hwpoisoned(folio)) {
 		folio_unlock(folio);
 		folio_put(folio);
-		*pagep = NULL;
 		return -EIO;
 	}
 
+	*foliop = folio;
 	return 0;
 }
 
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 22/23] ocfs2: Convert ocfs2_write_zero_page to use a folio
  2024-07-17 15:46 [PATCH 00/23] Convert write_begin / write_end to take a folio Matthew Wilcox (Oracle)
                   ` (20 preceding siblings ...)
  2024-07-17 15:47 ` [PATCH 21/23] fs: Convert aops->write_begin " Matthew Wilcox (Oracle)
@ 2024-07-17 15:47 ` Matthew Wilcox (Oracle)
  2024-07-17 15:47 ` [PATCH 23/23] buffer: Convert __block_write_begin() to take " Matthew Wilcox (Oracle)
                   ` (2 subsequent siblings)
  24 siblings, 0 replies; 31+ messages in thread
From: Matthew Wilcox (Oracle) @ 2024-07-17 15:47 UTC (permalink / raw)
  To: linux-fsdevel; +Cc: Matthew Wilcox (Oracle)

Removes a conversion of folio to page, and then two hidden conversions
of page back to folio.

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
 fs/ocfs2/file.c | 17 +++++++++--------
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index ccc57038a977..cfec1782ac2a 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -755,7 +755,7 @@ static int ocfs2_write_zero_page(struct inode *inode, u64 abs_from,
 				 u64 abs_to, struct buffer_head *di_bh)
 {
 	struct address_space *mapping = inode->i_mapping;
-	struct page *page;
+	struct folio *folio;
 	unsigned long index = abs_from >> PAGE_SHIFT;
 	handle_t *handle;
 	int ret = 0;
@@ -774,9 +774,10 @@ static int ocfs2_write_zero_page(struct inode *inode, u64 abs_from,
 		goto out;
 	}
 
-	page = find_or_create_page(mapping, index, GFP_NOFS);
-	if (!page) {
-		ret = -ENOMEM;
+	folio = __filemap_get_folio(mapping, index,
+			FGP_LOCK | FGP_ACCESSED | FGP_CREAT, GFP_NOFS);
+	if (IS_ERR(folio)) {
+		ret = PTR_ERR(folio);
 		mlog_errno(ret);
 		goto out_commit_trans;
 	}
@@ -803,7 +804,7 @@ static int ocfs2_write_zero_page(struct inode *inode, u64 abs_from,
 		 * __block_write_begin and block_commit_write to zero the
 		 * whole block.
 		 */
-		ret = __block_write_begin(page, block_start + 1, 0,
+		ret = __block_write_begin(&folio->page, block_start + 1, 0,
 					  ocfs2_get_block);
 		if (ret < 0) {
 			mlog_errno(ret);
@@ -812,7 +813,7 @@ static int ocfs2_write_zero_page(struct inode *inode, u64 abs_from,
 
 
 		/* must not update i_size! */
-		block_commit_write(page, block_start + 1, block_start + 1);
+		block_commit_write(&folio->page, block_start + 1, block_start + 1);
 	}
 
 	/*
@@ -833,8 +834,8 @@ static int ocfs2_write_zero_page(struct inode *inode, u64 abs_from,
 	}
 
 out_unlock:
-	unlock_page(page);
-	put_page(page);
+	folio_unlock(folio);
+	folio_put(folio);
 out_commit_trans:
 	if (handle)
 		ocfs2_commit_trans(OCFS2_SB(inode->i_sb), handle);
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 23/23] buffer: Convert __block_write_begin() to take a folio
  2024-07-17 15:46 [PATCH 00/23] Convert write_begin / write_end to take a folio Matthew Wilcox (Oracle)
                   ` (21 preceding siblings ...)
  2024-07-17 15:47 ` [PATCH 22/23] ocfs2: Convert ocfs2_write_zero_page to use " Matthew Wilcox (Oracle)
@ 2024-07-17 15:47 ` Matthew Wilcox (Oracle)
  2024-07-18 15:24 ` [PATCH 00/23] Convert write_begin / write_end " Josef Bacik
  2024-07-23  7:49 ` Christian Brauner
  24 siblings, 0 replies; 31+ messages in thread
From: Matthew Wilcox (Oracle) @ 2024-07-17 15:47 UTC (permalink / raw)
  To: linux-fsdevel; +Cc: Matthew Wilcox (Oracle)

Almost all callers have a folio now, so change __block_write_begin()
to take a folio and remove a call to compound_head().

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
 fs/buffer.c                 | 5 ++---
 fs/ext2/dir.c               | 2 +-
 fs/ext4/inline.c            | 6 +++---
 fs/ext4/inode.c             | 8 ++++----
 fs/minix/inode.c            | 2 +-
 fs/nilfs2/dir.c             | 2 +-
 fs/ocfs2/file.c             | 2 +-
 fs/reiserfs/inode.c         | 6 +++---
 fs/sysv/itree.c             | 2 +-
 fs/udf/file.c               | 2 +-
 fs/ufs/inode.c              | 2 +-
 include/linux/buffer_head.h | 2 +-
 12 files changed, 20 insertions(+), 21 deletions(-)

diff --git a/fs/buffer.c b/fs/buffer.c
index d52a740f7fca..45eb06cb1a4e 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -2168,11 +2168,10 @@ int __block_write_begin_int(struct folio *folio, loff_t pos, unsigned len,
 	return err;
 }
 
-int __block_write_begin(struct page *page, loff_t pos, unsigned len,
+int __block_write_begin(struct folio *folio, loff_t pos, unsigned len,
 		get_block_t *get_block)
 {
-	return __block_write_begin_int(page_folio(page), pos, len, get_block,
-				       NULL);
+	return __block_write_begin_int(folio, pos, len, get_block, NULL);
 }
 EXPORT_SYMBOL(__block_write_begin);
 
diff --git a/fs/ext2/dir.c b/fs/ext2/dir.c
index 60605fbdd0eb..2f3042d0174c 100644
--- a/fs/ext2/dir.c
+++ b/fs/ext2/dir.c
@@ -434,7 +434,7 @@ int ext2_inode_by_name(struct inode *dir, const struct qstr *child, ino_t *ino)
 
 static int ext2_prepare_chunk(struct folio *folio, loff_t pos, unsigned len)
 {
-	return __block_write_begin(&folio->page, pos, len, ext2_get_block);
+	return __block_write_begin(folio, pos, len, ext2_get_block);
 }
 
 static int ext2_handle_dirsync(struct inode *dir)
diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
index b7ea9cb4c398..d5c2f3b75084 100644
--- a/fs/ext4/inline.c
+++ b/fs/ext4/inline.c
@@ -601,10 +601,10 @@ static int ext4_convert_inline_data_to_extent(struct address_space *mapping,
 		goto out;
 
 	if (ext4_should_dioread_nolock(inode)) {
-		ret = __block_write_begin(&folio->page, from, to,
+		ret = __block_write_begin(folio, from, to,
 					  ext4_get_block_unwritten);
 	} else
-		ret = __block_write_begin(&folio->page, from, to, ext4_get_block);
+		ret = __block_write_begin(folio, from, to, ext4_get_block);
 
 	if (!ret && ext4_should_journal_data(inode)) {
 		ret = ext4_walk_page_buffers(handle, inode,
@@ -856,7 +856,7 @@ static int ext4_da_convert_inline_data_to_extent(struct address_space *mapping,
 			goto out;
 	}
 
-	ret = __block_write_begin(&folio->page, 0, inline_size,
+	ret = __block_write_begin(folio, 0, inline_size,
 				  ext4_da_get_block_prep);
 	if (ret) {
 		up_read(&EXT4_I(inode)->xattr_sem);
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 90ef8ec5c59b..03374dc215d1 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -1224,10 +1224,10 @@ static int ext4_write_begin(struct file *file, struct address_space *mapping,
 		ret = ext4_block_write_begin(folio, pos, len, ext4_get_block);
 #else
 	if (ext4_should_dioread_nolock(inode))
-		ret = __block_write_begin(&folio->page, pos, len,
+		ret = __block_write_begin(folio, pos, len,
 					  ext4_get_block_unwritten);
 	else
-		ret = __block_write_begin(&folio->page, pos, len, ext4_get_block);
+		ret = __block_write_begin(folio, pos, len, ext4_get_block);
 #endif
 	if (!ret && ext4_should_journal_data(inode)) {
 		ret = ext4_walk_page_buffers(handle, inode,
@@ -2962,7 +2962,7 @@ static int ext4_da_write_begin(struct file *file, struct address_space *mapping,
 #ifdef CONFIG_FS_ENCRYPTION
 	ret = ext4_block_write_begin(folio, pos, len, ext4_da_get_block_prep);
 #else
-	ret = __block_write_begin(&folio->page, pos, len, ext4_da_get_block_prep);
+	ret = __block_write_begin(folio, pos, len, ext4_da_get_block_prep);
 #endif
 	if (ret < 0) {
 		folio_unlock(folio);
@@ -6216,7 +6216,7 @@ vm_fault_t ext4_page_mkwrite(struct vm_fault *vmf)
 		if (folio_pos(folio) + len > size)
 			len = size - folio_pos(folio);
 
-		err = __block_write_begin(&folio->page, 0, len, ext4_get_block);
+		err = __block_write_begin(folio, 0, len, ext4_get_block);
 		if (!err) {
 			ret = VM_FAULT_SIGBUS;
 			if (ext4_journal_folio_buffers(handle, folio, len))
diff --git a/fs/minix/inode.c b/fs/minix/inode.c
index abb190c46c04..f007e389d5d2 100644
--- a/fs/minix/inode.c
+++ b/fs/minix/inode.c
@@ -429,7 +429,7 @@ static int minix_read_folio(struct file *file, struct folio *folio)
 
 int minix_prepare_chunk(struct folio *folio, loff_t pos, unsigned len)
 {
-	return __block_write_begin(&folio->page, pos, len, minix_get_block);
+	return __block_write_begin(folio, pos, len, minix_get_block);
 }
 
 static void minix_write_failed(struct address_space *mapping, loff_t to)
diff --git a/fs/nilfs2/dir.c b/fs/nilfs2/dir.c
index 66af42f88ca7..4b3e19d74925 100644
--- a/fs/nilfs2/dir.c
+++ b/fs/nilfs2/dir.c
@@ -83,7 +83,7 @@ static int nilfs_prepare_chunk(struct folio *folio, unsigned int from,
 {
 	loff_t pos = folio_pos(folio) + from;
 
-	return __block_write_begin(&folio->page, pos, to - from, nilfs_get_block);
+	return __block_write_begin(folio, pos, to - from, nilfs_get_block);
 }
 
 static void nilfs_commit_chunk(struct folio *folio,
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index cfec1782ac2a..d058eb30cfc2 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -804,7 +804,7 @@ static int ocfs2_write_zero_page(struct inode *inode, u64 abs_from,
 		 * __block_write_begin and block_commit_write to zero the
 		 * whole block.
 		 */
-		ret = __block_write_begin(&folio->page, block_start + 1, 0,
+		ret = __block_write_begin(folio, block_start + 1, 0,
 					  ocfs2_get_block);
 		if (ret < 0) {
 			mlog_errno(ret);
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index ea23872ba24f..72c53129c952 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -2198,7 +2198,7 @@ static int grab_tail_page(struct inode *inode,
 	/* start within the page of the last block in the file */
 	start = (offset / blocksize) * blocksize;
 
-	error = __block_write_begin(&folio->page, start, offset - start,
+	error = __block_write_begin(folio, start, offset - start,
 				    reiserfs_get_block_create_0);
 	if (error)
 		goto unlock;
@@ -2762,7 +2762,7 @@ static int reiserfs_write_begin(struct file *file,
 		old_ref = th->t_refcount;
 		th->t_refcount++;
 	}
-	ret = __block_write_begin(&folio->page, pos, len, reiserfs_get_block);
+	ret = __block_write_begin(folio, pos, len, reiserfs_get_block);
 	if (ret && reiserfs_transaction_running(inode->i_sb)) {
 		struct reiserfs_transaction_handle *th = current->journal_info;
 		/*
@@ -2822,7 +2822,7 @@ int __reiserfs_write_begin(struct page *page, unsigned from, unsigned len)
 		th->t_refcount++;
 	}
 
-	ret = __block_write_begin(page, from, len, reiserfs_get_block);
+	ret = __block_write_begin(page_folio(page), from, len, reiserfs_get_block);
 	if (ret && reiserfs_transaction_running(inode->i_sb)) {
 		struct reiserfs_transaction_handle *th = current->journal_info;
 		/*
diff --git a/fs/sysv/itree.c b/fs/sysv/itree.c
index 8864438817a6..451e95f474fa 100644
--- a/fs/sysv/itree.c
+++ b/fs/sysv/itree.c
@@ -468,7 +468,7 @@ static int sysv_read_folio(struct file *file, struct folio *folio)
 
 int sysv_prepare_chunk(struct folio *folio, loff_t pos, unsigned len)
 {
-	return __block_write_begin(&folio->page, pos, len, get_block);
+	return __block_write_begin(folio, pos, len, get_block);
 }
 
 static void sysv_write_failed(struct address_space *mapping, loff_t to)
diff --git a/fs/udf/file.c b/fs/udf/file.c
index 3a4179de316b..412fe7c4d348 100644
--- a/fs/udf/file.c
+++ b/fs/udf/file.c
@@ -62,7 +62,7 @@ static vm_fault_t udf_page_mkwrite(struct vm_fault *vmf)
 		end = size & ~PAGE_MASK;
 	else
 		end = PAGE_SIZE;
-	err = __block_write_begin(&folio->page, 0, end, udf_get_block);
+	err = __block_write_begin(folio, 0, end, udf_get_block);
 	if (err) {
 		folio_unlock(folio);
 		ret = vmf_fs_error(err);
diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c
index f43461652d9f..5331ae7ebf3e 100644
--- a/fs/ufs/inode.c
+++ b/fs/ufs/inode.c
@@ -481,7 +481,7 @@ static int ufs_read_folio(struct file *file, struct folio *folio)
 
 int ufs_prepare_chunk(struct folio *folio, loff_t pos, unsigned len)
 {
-	return __block_write_begin(&folio->page, pos, len, ufs_getfrag_block);
+	return __block_write_begin(folio, pos, len, ufs_getfrag_block);
 }
 
 static void ufs_truncate_blocks(struct inode *);
diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h
index 254563a2a9de..c85e65fd4cdc 100644
--- a/include/linux/buffer_head.h
+++ b/include/linux/buffer_head.h
@@ -259,7 +259,7 @@ int block_read_full_folio(struct folio *, get_block_t *);
 bool block_is_partially_uptodate(struct folio *, size_t from, size_t count);
 int block_write_begin(struct address_space *mapping, loff_t pos, unsigned len,
 		struct folio **foliop, get_block_t *get_block);
-int __block_write_begin(struct page *page, loff_t pos, unsigned len,
+int __block_write_begin(struct folio *folio, loff_t pos, unsigned len,
 		get_block_t *get_block);
 int block_write_end(struct file *, struct address_space *,
 				loff_t, unsigned len, unsigned copied,
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* Re: [PATCH 00/23] Convert write_begin / write_end to take a folio
  2024-07-17 15:46 [PATCH 00/23] Convert write_begin / write_end to take a folio Matthew Wilcox (Oracle)
                   ` (22 preceding siblings ...)
  2024-07-17 15:47 ` [PATCH 23/23] buffer: Convert __block_write_begin() to take " Matthew Wilcox (Oracle)
@ 2024-07-18 15:24 ` Josef Bacik
  2024-07-23  7:49 ` Christian Brauner
  24 siblings, 0 replies; 31+ messages in thread
From: Josef Bacik @ 2024-07-18 15:24 UTC (permalink / raw)
  To: Matthew Wilcox (Oracle); +Cc: linux-fsdevel

On Wed, Jul 17, 2024 at 04:46:50PM +0100, Matthew Wilcox (Oracle) wrote:
> You can find the full branch at
> http://git.infradead.org/?p=users/willy/pagecache.git;a=shortlog;h=refs/heads/write-end
> aka
> git://git.infradead.org/users/willy/pagecache.git write-end
> 
> On top of the ufs, minix, sysv and qnx6 directory handling patches, this
> patch series converts us to using folios for write_begin and write_end.
> That's the last mention of 'struct page' in several filesystems.
> 
> I'd like to get some version of these patches into the 6.12 merge
> window.
> 
> Matthew Wilcox (Oracle) (23):
>   reiserfs: Convert grab_tail_page() to use a folio
>   reiserfs: Convert reiserfs_write_begin() to use a folio
>   block: Use a folio in blkdev_write_end()
>   buffer: Use a folio in generic_write_end()
>   nilfs2: Use a folio in nilfs_recover_dsync_blocks()
>   ntfs3: Remove reset_log_file()
>   buffer: Convert block_write_end() to take a folio
>   ecryptfs: Convert ecryptfs_write_end() to use a folio
>   ecryptfs: Use a folio in ecryptfs_write_begin()
>   f2fs: Convert f2fs_write_end() to use a folio
>   f2fs: Convert f2fs_write_begin() to use a folio
>   fuse: Convert fuse_write_end() to use a folio
>   fuse: Convert fuse_write_begin() to use a folio
>   hostfs: Convert hostfs_write_end() to use a folio
>   jffs2: Convert jffs2_write_end() to use a folio
>   jffs2: Convert jffs2_write_begin() to use a folio
>   orangefs: Convert orangefs_write_end() to use a folio
>   orangefs: Convert orangefs_write_begin() to use a folio
>   vboxsf: Use a folio in vboxsf_write_end()
>   fs: Convert aops->write_end to take a folio
>   fs: Convert aops->write_begin to take a folio
>   ocfs2: Convert ocfs2_write_zero_page to use a folio
>   buffer: Convert __block_write_begin() to take a folio

I applied and reviewed this, the per-fs stuff obviously I'm less familiar with,
I mostly just validated it was 1:1 conversion and that the behavior matched the
previous behavior.  You can add

Reviewed-by: Josef Bacik <josef@toxicpanda.com>

to the series.  Thanks,

Josef

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 05/23] nilfs2: Use a folio in nilfs_recover_dsync_blocks()
  2024-07-17 15:46 ` [PATCH 05/23] nilfs2: Use a folio in nilfs_recover_dsync_blocks() Matthew Wilcox (Oracle)
@ 2024-07-18 17:14   ` Ryusuke Konishi
  0 siblings, 0 replies; 31+ messages in thread
From: Ryusuke Konishi @ 2024-07-18 17:14 UTC (permalink / raw)
  To: Matthew Wilcox (Oracle); +Cc: linux-fsdevel

On Thu, Jul 18, 2024 at 12:54 AM Matthew Wilcox (Oracle) wrote:
>
> Replaces four hidden calls to compound_head() with one.
>
> Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
> ---
>  fs/nilfs2/recovery.c | 10 ++++++----
>  1 file changed, 6 insertions(+), 4 deletions(-)
>

I've checked this patch (and the big-bang patches as well, mainly for
the nilfs2 related parts).
The conversion was straightforward and I didn't find any issues.

Feel free to add

Acked-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>

to this.  Thanks.

Ryusuke Konishi

> diff --git a/fs/nilfs2/recovery.c b/fs/nilfs2/recovery.c
> index b638dc06df2f..15653701b1c8 100644
> --- a/fs/nilfs2/recovery.c
> +++ b/fs/nilfs2/recovery.c
> @@ -499,6 +499,7 @@ static int nilfs_recover_dsync_blocks(struct the_nilfs *nilfs,
>         struct nilfs_recovery_block *rb, *n;
>         unsigned int blocksize = nilfs->ns_blocksize;
>         struct page *page;
> +       struct folio *folio;
>         loff_t pos;
>         int err = 0, err2 = 0;
>
> @@ -522,6 +523,7 @@ static int nilfs_recover_dsync_blocks(struct the_nilfs *nilfs,
>                         goto failed_inode;
>                 }
>
> +               folio = page_folio(page);
>                 err = nilfs_recovery_copy_block(nilfs, rb, pos, page);
>                 if (unlikely(err))
>                         goto failed_page;
> @@ -533,15 +535,15 @@ static int nilfs_recover_dsync_blocks(struct the_nilfs *nilfs,
>                 block_write_end(NULL, inode->i_mapping, pos, blocksize,
>                                 blocksize, page, NULL);
>
> -               unlock_page(page);
> -               put_page(page);
> +               folio_unlock(folio);
> +               folio_put(folio);
>
>                 (*nr_salvaged_blocks)++;
>                 goto next;
>
>   failed_page:
> -               unlock_page(page);
> -               put_page(page);
> +               folio_unlock(folio);
> +               folio_put(folio);
>
>   failed_inode:
>                 nilfs_warn(sb,
> --
> 2.43.0
>
>

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 00/23] Convert write_begin / write_end to take a folio
  2024-07-17 15:46 [PATCH 00/23] Convert write_begin / write_end to take a folio Matthew Wilcox (Oracle)
                   ` (23 preceding siblings ...)
  2024-07-18 15:24 ` [PATCH 00/23] Convert write_begin / write_end " Josef Bacik
@ 2024-07-23  7:49 ` Christian Brauner
  2024-07-23 13:20   ` Matthew Wilcox
  24 siblings, 1 reply; 31+ messages in thread
From: Christian Brauner @ 2024-07-23  7:49 UTC (permalink / raw)
  To: Matthew Wilcox (Oracle); +Cc: linux-fsdevel

On Wed, Jul 17, 2024 at 04:46:50PM GMT, Matthew Wilcox wrote:
> You can find the full branch at
> http://git.infradead.org/?p=users/willy/pagecache.git;a=shortlog;h=refs/heads/write-end
> aka
> git://git.infradead.org/users/willy/pagecache.git write-end
> 
> On top of the ufs, minix, sysv and qnx6 directory handling patches, this
> patch series converts us to using folios for write_begin and write_end.
> That's the last mention of 'struct page' in several filesystems.
> 
> I'd like to get some version of these patches into the 6.12 merge
> window.

Is it stable enough that I can already pull it from you?
I'd like this to be based on v6.11-rc1.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 00/23] Convert write_begin / write_end to take a folio
  2024-07-23  7:49 ` Christian Brauner
@ 2024-07-23 13:20   ` Matthew Wilcox
  2024-07-23 13:41     ` Christian Brauner
  0 siblings, 1 reply; 31+ messages in thread
From: Matthew Wilcox @ 2024-07-23 13:20 UTC (permalink / raw)
  To: Christian Brauner; +Cc: linux-fsdevel

On Tue, Jul 23, 2024 at 09:49:10AM +0200, Christian Brauner wrote:
> On Wed, Jul 17, 2024 at 04:46:50PM GMT, Matthew Wilcox wrote:
> > You can find the full branch at
> > http://git.infradead.org/?p=users/willy/pagecache.git;a=shortlog;h=refs/heads/write-end
> > aka
> > git://git.infradead.org/users/willy/pagecache.git write-end
> > 
> > On top of the ufs, minix, sysv and qnx6 directory handling patches, this
> > patch series converts us to using folios for write_begin and write_end.
> > That's the last mention of 'struct page' in several filesystems.
> > 
> > I'd like to get some version of these patches into the 6.12 merge
> > window.
> 
> Is it stable enough that I can already pull it from you?
> I'd like this to be based on v6.11-rc1.

It's stable in that it works, but it's still based on linux-next.  I think
it probably depends on a few fs git pulls that are still outstanding.
More awkwardly for merging is that it depends on the four directory
handling patch series, each of which you've put on a separate topic
branch.  So I'm not sure how you want to handle that.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 00/23] Convert write_begin / write_end to take a folio
  2024-07-23 13:20   ` Matthew Wilcox
@ 2024-07-23 13:41     ` Christian Brauner
  2024-07-23 22:54       ` Matthew Wilcox
  0 siblings, 1 reply; 31+ messages in thread
From: Christian Brauner @ 2024-07-23 13:41 UTC (permalink / raw)
  To: Matthew Wilcox; +Cc: linux-fsdevel

On Tue, Jul 23, 2024 at 02:20:46PM GMT, Matthew Wilcox wrote:
> On Tue, Jul 23, 2024 at 09:49:10AM +0200, Christian Brauner wrote:
> > On Wed, Jul 17, 2024 at 04:46:50PM GMT, Matthew Wilcox wrote:
> > > You can find the full branch at
> > > http://git.infradead.org/?p=users/willy/pagecache.git;a=shortlog;h=refs/heads/write-end
> > > aka
> > > git://git.infradead.org/users/willy/pagecache.git write-end
> > > 
> > > On top of the ufs, minix, sysv and qnx6 directory handling patches, this
> > > patch series converts us to using folios for write_begin and write_end.
> > > That's the last mention of 'struct page' in several filesystems.
> > > 
> > > I'd like to get some version of these patches into the 6.12 merge
> > > window.
> > 
> > Is it stable enough that I can already pull it from you?
> > I'd like this to be based on v6.11-rc1.
> 
> It's stable in that it works, but it's still based on linux-next.  I think
> it probably depends on a few fs git pulls that are still outstanding.
> More awkwardly for merging is that it depends on the four directory
> handling patch series, each of which you've put on a separate topic
> branch.  So I'm not sure how you want to handle that.

I've put them there before this series here surfaced. But anyway,
there's plenty of options. I can merge all separate topic branches
together in a main branch or I can just pull it all in together. That
depends how complex it turns out to be.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 00/23] Convert write_begin / write_end to take a folio
  2024-07-23 13:41     ` Christian Brauner
@ 2024-07-23 22:54       ` Matthew Wilcox
  2024-07-30 14:23         ` Christian Brauner
  0 siblings, 1 reply; 31+ messages in thread
From: Matthew Wilcox @ 2024-07-23 22:54 UTC (permalink / raw)
  To: Christian Brauner; +Cc: linux-fsdevel

On Tue, Jul 23, 2024 at 03:41:37PM +0200, Christian Brauner wrote:
> On Tue, Jul 23, 2024 at 02:20:46PM GMT, Matthew Wilcox wrote:
> > On Tue, Jul 23, 2024 at 09:49:10AM +0200, Christian Brauner wrote:
> > > On Wed, Jul 17, 2024 at 04:46:50PM GMT, Matthew Wilcox wrote:
> > > > You can find the full branch at
> > > > http://git.infradead.org/?p=users/willy/pagecache.git;a=shortlog;h=refs/heads/write-end
> > > > aka
> > > > git://git.infradead.org/users/willy/pagecache.git write-end
> > > > 
> > > > On top of the ufs, minix, sysv and qnx6 directory handling patches, this
> > > > patch series converts us to using folios for write_begin and write_end.
> > > > That's the last mention of 'struct page' in several filesystems.
> > > > 
> > > > I'd like to get some version of these patches into the 6.12 merge
> > > > window.
> > > 
> > > Is it stable enough that I can already pull it from you?
> > > I'd like this to be based on v6.11-rc1.
> > 
> > It's stable in that it works, but it's still based on linux-next.  I think
> > it probably depends on a few fs git pulls that are still outstanding.
> > More awkwardly for merging is that it depends on the four directory
> > handling patch series, each of which you've put on a separate topic
> > branch.  So I'm not sure how you want to handle that.
> 
> I've put them there before this series here surfaced. But anyway,
> there's plenty of options. I can merge all separate topic branches
> together in a main branch or I can just pull it all in together. That
> depends how complex it turns out to be.

I've rebased to current-ish Linus, updated to commit f45c4246ab18 at
the above URL.  It all seems to work well enough, so I'm not relying on
any later commits.  I can rebase it onto -rc1 when it is tagged, or
you can pull it now if you'd rather.  It's missing the R-b/A-b tags
from Josef & Ryusuke Konishi.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 00/23] Convert write_begin / write_end to take a folio
  2024-07-23 22:54       ` Matthew Wilcox
@ 2024-07-30 14:23         ` Christian Brauner
  0 siblings, 0 replies; 31+ messages in thread
From: Christian Brauner @ 2024-07-30 14:23 UTC (permalink / raw)
  To: Matthew Wilcox; +Cc: linux-fsdevel

On Tue, Jul 23, 2024 at 11:54:25PM GMT, Matthew Wilcox wrote:
> On Tue, Jul 23, 2024 at 03:41:37PM +0200, Christian Brauner wrote:
> > On Tue, Jul 23, 2024 at 02:20:46PM GMT, Matthew Wilcox wrote:
> > > On Tue, Jul 23, 2024 at 09:49:10AM +0200, Christian Brauner wrote:
> > > > On Wed, Jul 17, 2024 at 04:46:50PM GMT, Matthew Wilcox wrote:
> > > > > You can find the full branch at
> > > > > http://git.infradead.org/?p=users/willy/pagecache.git;a=shortlog;h=refs/heads/write-end
> > > > > aka
> > > > > git://git.infradead.org/users/willy/pagecache.git write-end
> > > > > 
> > > > > On top of the ufs, minix, sysv and qnx6 directory handling patches, this
> > > > > patch series converts us to using folios for write_begin and write_end.
> > > > > That's the last mention of 'struct page' in several filesystems.
> > > > > 
> > > > > I'd like to get some version of these patches into the 6.12 merge
> > > > > window.
> > > > 
> > > > Is it stable enough that I can already pull it from you?
> > > > I'd like this to be based on v6.11-rc1.
> > > 
> > > It's stable in that it works, but it's still based on linux-next.  I think
> > > it probably depends on a few fs git pulls that are still outstanding.
> > > More awkwardly for merging is that it depends on the four directory
> > > handling patch series, each of which you've put on a separate topic
> > > branch.  So I'm not sure how you want to handle that.
> > 
> > I've put them there before this series here surfaced. But anyway,
> > there's plenty of options. I can merge all separate topic branches
> > together in a main branch or I can just pull it all in together. That
> > depends how complex it turns out to be.
> 
> I've rebased to current-ish Linus, updated to commit f45c4246ab18 at
> the above URL.  It all seems to work well enough, so I'm not relying on
> any later commits.  I can rebase it onto -rc1 when it is tagged, or
> you can pull it now if you'd rather.  It's missing the R-b/A-b tags
> from Josef & Ryusuke Konishi.

I've rebased to v6.11-rc1 and added the missing Acks. I also added your
SoB to "qnx6: Convert directory handling to use kmap_local" which was
missing. Let me know if anything looks wrong. It's in the vfs.folio
branch.

^ permalink raw reply	[flat|nested] 31+ messages in thread

end of thread, other threads:[~2024-07-30 14:23 UTC | newest]

Thread overview: 31+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-07-17 15:46 [PATCH 00/23] Convert write_begin / write_end to take a folio Matthew Wilcox (Oracle)
2024-07-17 15:46 ` [PATCH 01/23] reiserfs: Convert grab_tail_page() to use " Matthew Wilcox (Oracle)
2024-07-17 15:46 ` [PATCH 02/23] reiserfs: Convert reiserfs_write_begin() " Matthew Wilcox (Oracle)
2024-07-17 15:46 ` [PATCH 03/23] block: Use a folio in blkdev_write_end() Matthew Wilcox (Oracle)
2024-07-17 15:46 ` [PATCH 04/23] buffer: Use a folio in generic_write_end() Matthew Wilcox (Oracle)
2024-07-17 15:46 ` [PATCH 05/23] nilfs2: Use a folio in nilfs_recover_dsync_blocks() Matthew Wilcox (Oracle)
2024-07-18 17:14   ` Ryusuke Konishi
2024-07-17 15:46 ` [PATCH 06/23] ntfs3: Remove reset_log_file() Matthew Wilcox (Oracle)
2024-07-17 15:46 ` [PATCH 07/23] buffer: Convert block_write_end() to take a folio Matthew Wilcox (Oracle)
2024-07-17 15:46 ` [PATCH 08/23] ecryptfs: Convert ecryptfs_write_end() to use " Matthew Wilcox (Oracle)
2024-07-17 15:46 ` [PATCH 09/23] ecryptfs: Use a folio in ecryptfs_write_begin() Matthew Wilcox (Oracle)
2024-07-17 15:47 ` [PATCH 10/23] f2fs: Convert f2fs_write_end() to use a folio Matthew Wilcox (Oracle)
2024-07-17 15:47 ` [PATCH 11/23] f2fs: Convert f2fs_write_begin() " Matthew Wilcox (Oracle)
2024-07-17 15:47 ` [PATCH 12/23] fuse: Convert fuse_write_end() " Matthew Wilcox (Oracle)
2024-07-17 15:47 ` [PATCH 13/23] fuse: Convert fuse_write_begin() " Matthew Wilcox (Oracle)
2024-07-17 15:47 ` [PATCH 14/23] hostfs: Convert hostfs_write_end() " Matthew Wilcox (Oracle)
2024-07-17 15:47 ` [PATCH 15/23] jffs2: Convert jffs2_write_end() " Matthew Wilcox (Oracle)
2024-07-17 15:47 ` [PATCH 16/23] jffs2: Convert jffs2_write_begin() " Matthew Wilcox (Oracle)
2024-07-17 15:47 ` [PATCH 17/23] orangefs: Convert orangefs_write_end() " Matthew Wilcox (Oracle)
2024-07-17 15:47 ` [PATCH 18/23] orangefs: Convert orangefs_write_begin() " Matthew Wilcox (Oracle)
2024-07-17 15:47 ` [PATCH 19/23] vboxsf: Use a folio in vboxsf_write_end() Matthew Wilcox (Oracle)
2024-07-17 15:47 ` [PATCH 20/23] fs: Convert aops->write_end to take a folio Matthew Wilcox (Oracle)
2024-07-17 15:47 ` [PATCH 21/23] fs: Convert aops->write_begin " Matthew Wilcox (Oracle)
2024-07-17 15:47 ` [PATCH 22/23] ocfs2: Convert ocfs2_write_zero_page to use " Matthew Wilcox (Oracle)
2024-07-17 15:47 ` [PATCH 23/23] buffer: Convert __block_write_begin() to take " Matthew Wilcox (Oracle)
2024-07-18 15:24 ` [PATCH 00/23] Convert write_begin / write_end " Josef Bacik
2024-07-23  7:49 ` Christian Brauner
2024-07-23 13:20   ` Matthew Wilcox
2024-07-23 13:41     ` Christian Brauner
2024-07-23 22:54       ` Matthew Wilcox
2024-07-30 14:23         ` Christian Brauner

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).