Re: [PATCH 10/12] iomap: replace iomap_folio_ops with iomap_write_ops

Brian Foster
2025-06-27T19:14:56Z

On Fri, Jun 27, 2025 at 09:02:43AM +0200, Christoph Hellwig wrote:
> The iomap_folio_ops are only used for buffered writes, including
> the zero and unshare variants. Rename them to iomap_write_ops
> to better describe the usage, and pass them through the callchain
> like the other operation specific methods instead of through the
> iomap.
>
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> ---
> Documentation/filesystems/iomap/design.rst | 3 -
> .../filesystems/iomap/operations.rst | 8 +-
> block/fops.c | 3 +-
> fs/gfs2/bmap.c | 21 ++---
> fs/gfs2/bmap.h | 1 +
> fs/gfs2/file.c | 3 +-
> fs/iomap/buffered-io.c | 79 +++++++++++--------
> fs/xfs/xfs_file.c | 6 +-
> fs/xfs/xfs_iomap.c | 12 ++-
> fs/xfs/xfs_iomap.h | 1 +
> fs/xfs/xfs_reflink.c | 3 +-
> fs/zonefs/file.c | 3 +-
> include/linux/iomap.h | 22 +++---
> 13 files changed, 89 insertions(+), 76 deletions(-)
>
...
> diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
> index ff05e6b1b0bb..2e94a9435002 100644
> --- a/fs/xfs/xfs_iomap.c
> +++ b/fs/xfs/xfs_iomap.c
> @@ -79,6 +79,9 @@ xfs_iomap_valid(
> {
> struct xfs_inode *ip = XFS_I(inode);
>
> + if (iomap->type == IOMAP_HOLE)
> + return true;
> +

Is this to handle the xfs_hole_to_iomap() case? I.e., no validity cookie
and no folio_ops set..? If so, I think a small comment would be helpful.
Otherwise LGTM:

Reviewed-by: Brian Foster <bfoster@redhat.com>

> if (iomap->validity_cookie !=
> xfs_iomap_inode_sequence(ip, iomap->flags)) {
> trace_xfs_iomap_invalid(ip, iomap);
> @@ -89,7 +92,7 @@ xfs_iomap_valid(
> return true;
> }
>
> -static const struct iomap_folio_ops xfs_iomap_folio_ops = {
> +const struct iomap_write_ops xfs_iomap_write_ops = {
> .iomap_valid = xfs_iomap_valid,
> };
>
> @@ -151,7 +154,6 @@ xfs_bmbt_to_iomap(
> iomap->flags |= IOMAP_F_DIRTY;
>
> iomap->validity_cookie = sequence_cookie;
> - iomap->folio_ops = &xfs_iomap_folio_ops;
> return 0;
> }
>
> @@ -2198,7 +2200,8 @@ xfs_zero_range(
> return dax_zero_range(inode, pos, len, did_zero,
> &xfs_dax_write_iomap_ops);
> return iomap_zero_range(inode, pos, len, did_zero,
> - &xfs_buffered_write_iomap_ops, ac);
> + &xfs_buffered_write_iomap_ops, &xfs_iomap_write_ops,
> + ac);
> }
>
> int
> @@ -2214,5 +2217,6 @@ xfs_truncate_page(
> return dax_truncate_page(inode, pos, did_zero,
> &xfs_dax_write_iomap_ops);
> return iomap_truncate_page(inode, pos, did_zero,
> - &xfs_buffered_write_iomap_ops, ac);
> + &xfs_buffered_write_iomap_ops, &xfs_iomap_write_ops,
> + ac);
> }
> diff --git a/fs/xfs/xfs_iomap.h b/fs/xfs/xfs_iomap.h
> index 674f8ac1b9bd..ebcce7d49446 100644
> --- a/fs/xfs/xfs_iomap.h
> +++ b/fs/xfs/xfs_iomap.h
> @@ -57,5 +57,6 @@ extern const struct iomap_ops xfs_seek_iomap_ops;
> extern const struct iomap_ops xfs_xattr_iomap_ops;
> extern const struct iomap_ops xfs_dax_write_iomap_ops;
> extern const struct iomap_ops xfs_atomic_write_cow_iomap_ops;
> +extern const struct iomap_write_ops xfs_iomap_write_ops;
>
> #endif /* __XFS_IOMAP_H__*/
> diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c
> index ad3bcb76d805..3f177b4ec131 100644
> --- a/fs/xfs/xfs_reflink.c
> +++ b/fs/xfs/xfs_reflink.c
> @@ -1881,7 +1881,8 @@ xfs_reflink_unshare(
> &xfs_dax_write_iomap_ops);
> else
> error = iomap_file_unshare(inode, offset, len,
> - &xfs_buffered_write_iomap_ops);
> + &xfs_buffered_write_iomap_ops,
> + &xfs_iomap_write_ops);
> if (error)
> goto out;
>
> diff --git a/fs/zonefs/file.c b/fs/zonefs/file.c
> index a0ce6c97b9e5..88cb7df2709f 100644
> --- a/fs/zonefs/file.c
> +++ b/fs/zonefs/file.c
> @@ -572,7 +572,8 @@ static ssize_t zonefs_file_buffered_write(struct kiocb *iocb,
> if (ret <= 0)
> goto inode_unlock;
>
> - ret = iomap_file_buffered_write(iocb, from, &zonefs_write_iomap_ops, NULL);
> + ret = iomap_file_buffered_write(iocb, from, &zonefs_write_iomap_ops,
> + NULL, NULL);
> if (ret == -EIO)
> zonefs_io_error(inode, true);
>
> diff --git a/include/linux/iomap.h b/include/linux/iomap.h
> index 568a246f949b..482787013ff7 100644
> --- a/include/linux/iomap.h
> +++ b/include/linux/iomap.h
> @@ -101,8 +101,6 @@ struct vm_fault;
> */
> #define IOMAP_NULL_ADDR -1ULL /* addr is not valid */
>
> -struct iomap_folio_ops;
> -
> struct iomap {
> u64 addr; /* disk offset of mapping, bytes */
> loff_t offset; /* file offset of mapping, bytes */
> @@ -113,7 +111,6 @@ struct iomap {
> struct dax_device *dax_dev; /* dax_dev for dax operations */
> void *inline_data;
> void *private; /* filesystem private */
> - const struct iomap_folio_ops *folio_ops;
> u64 validity_cookie; /* used with .iomap_valid() */
> };
>
> @@ -143,16 +140,11 @@ static inline bool iomap_inline_data_valid(const struct iomap *iomap)
> }
>
> /*
> - * When a filesystem sets folio_ops in an iomap mapping it returns, get_folio
> - * and put_folio will be called for each folio written to. This only applies
> - * to buffered writes as unbuffered writes will not typically have folios
> - * associated with them.
> - *
> * When get_folio succeeds, put_folio will always be called to do any
> * cleanup work necessary. put_folio is responsible for unlocking and putting
> * @folio.
> */
> -struct iomap_folio_ops {
> +struct iomap_write_ops {
> struct folio *(*get_folio)(struct iomap_iter *iter, loff_t pos,
> unsigned len);
> void (*put_folio)(struct inode *inode, loff_t pos, unsigned copied,
> @@ -335,7 +327,8 @@ static inline bool iomap_want_unshare_iter(const struct iomap_iter *iter)
> }
>
> ssize_t iomap_file_buffered_write(struct kiocb *iocb, struct iov_iter *from,
> - const struct iomap_ops *ops, void *private);
> + const struct iomap_ops *ops,
> + const struct iomap_write_ops *write_ops, void *private);
> int iomap_read_folio(struct folio *folio, const struct iomap_ops *ops);
> void iomap_readahead(struct readahead_control *, const struct iomap_ops *ops);
> bool iomap_is_partially_uptodate(struct folio *, size_t from, size_t count);
> @@ -344,11 +337,14 @@ bool iomap_release_folio(struct folio *folio, gfp_t gfp_flags);
> void iomap_invalidate_folio(struct folio *folio, size_t offset, size_t len);
> bool iomap_dirty_folio(struct address_space *mapping, struct folio *folio);
> int iomap_file_unshare(struct inode *inode, loff_t pos, loff_t len,
> - const struct iomap_ops *ops);
> + const struct iomap_ops *ops,
> + const struct iomap_write_ops *write_ops);
> int iomap_zero_range(struct inode *inode, loff_t pos, loff_t len,
> - bool *did_zero, const struct iomap_ops *ops, void *private);
> + bool *did_zero, const struct iomap_ops *ops,
> + const struct iomap_write_ops *write_ops, void *private);
> int iomap_truncate_page(struct inode *inode, loff_t pos, bool *did_zero,
> - const struct iomap_ops *ops, void *private);
> + const struct iomap_ops *ops,
> + const struct iomap_write_ops *write_ops, void *private);
> vm_fault_t iomap_page_mkwrite(struct vm_fault *vmf, const struct iomap_ops *ops,
> void *private);
> typedef void (*iomap_punch_t)(struct inode *inode, loff_t offset, loff_t length,
> --
> 2.47.2
>
>