]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
xfs: replace zero range flush with folio batch
authorBrian Foster <bfoster@redhat.com>
Wed, 11 Mar 2026 16:25:01 +0000 (12:25 -0400)
committerCarlos Maiolino <cem@kernel.org>
Mon, 23 Mar 2026 10:07:59 +0000 (11:07 +0100)
Now that the zero range pagecache flush is purely isolated to
providing zeroing correctness in this case, we can remove it and
replace it with the folio batch mechanism that is used for handling
unwritten extents.

This is still slightly odd in that XFS reports a hole vs. a mapping
that reflects the COW fork extents, but that has always been the
case in this situation and so a separate issue. We drop the iomap
warning that assumes the folio batch is always associated with
unwritten mappings, but this is mainly a development assertion as
otherwise the core iomap fbatch code doesn't care much about the
mapping type if it's handed the set of folios to process.

Signed-off-by: Brian Foster <bfoster@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
fs/iomap/buffered-io.c
fs/xfs/xfs_iomap.c

index e5e7127a4e929f56faddd01186d6dd82ea55ea3a..3be3627d4b50454911ec7d3b445bdd73eb5b285e 100644 (file)
@@ -1632,10 +1632,6 @@ iomap_zero_range(struct inode *inode, loff_t pos, loff_t len, bool *did_zero,
        while ((ret = iomap_iter(&iter, ops)) > 0) {
                const struct iomap *srcmap = iomap_iter_srcmap(&iter);
 
-               if (WARN_ON_ONCE((iter.iomap.flags & IOMAP_F_FOLIO_BATCH) &&
-                                srcmap->type != IOMAP_UNWRITTEN))
-                       return -EIO;
-
                if (!(iter.iomap.flags & IOMAP_F_FOLIO_BATCH) &&
                    (srcmap->type == IOMAP_HOLE ||
                     srcmap->type == IOMAP_UNWRITTEN)) {
index 6229a0bf793b6c7c1ac4f78d49145f9fe9061fe5..51a55510d4a5131d2db6af65e82a46ed6bb79629 100644 (file)
@@ -1781,7 +1781,6 @@ xfs_buffered_write_iomap_begin(
 {
        struct iomap_iter       *iter = container_of(iomap, struct iomap_iter,
                                                     iomap);
-       struct address_space    *mapping = inode->i_mapping;
        struct xfs_inode        *ip = XFS_I(inode);
        struct xfs_mount        *mp = ip->i_mount;
        xfs_fileoff_t           offset_fsb = XFS_B_TO_FSBT(mp, offset);
@@ -1813,7 +1812,6 @@ xfs_buffered_write_iomap_begin(
        if (error)
                return error;
 
-restart:
        error = xfs_ilock_for_iomap(ip, flags, &lockmode);
        if (error)
                return error;
@@ -1866,8 +1864,8 @@ restart:
 
        /*
         * We may need to zero over a hole in the data fork if it's fronted by
-        * COW blocks and dirty pagecache. To make sure zeroing occurs, force
-        * writeback to remap pending blocks and restart the lookup.
+        * COW blocks and dirty pagecache. Scan such file ranges for dirty
+        * cache and fill the iomap batch with folios that need zeroing.
         */
        if ((flags & IOMAP_ZERO) && imap.br_startoff > offset_fsb) {
                loff_t  start, end;
@@ -1889,16 +1887,10 @@ restart:
                xfs_trim_extent(&imap, offset_fsb,
                            cmap.br_startoff + cmap.br_blockcount - offset_fsb);
                start = XFS_FSB_TO_B(mp, imap.br_startoff);
-               end = XFS_FSB_TO_B(mp,
-                                  imap.br_startoff + imap.br_blockcount) - 1;
-               if (filemap_range_needs_writeback(mapping, start, end)) {
-                       xfs_iunlock(ip, lockmode);
-                       error = filemap_write_and_wait_range(mapping, start,
-                                                            end);
-                       if (error)
-                               return error;
-                       goto restart;
-               }
+               end = XFS_FSB_TO_B(mp, imap.br_startoff + imap.br_blockcount);
+               iomap_fill_dirty_folios(iter, &start, end, &iomap_flags);
+               xfs_trim_extent(&imap, offset_fsb,
+                               XFS_B_TO_FSB(mp, start) - offset_fsb);
 
                goto found_imap;
        }