]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
iomap: rework iomap_write_begin() to return folio offset and length
authorBrian Foster <bfoster@redhat.com>
Tue, 6 May 2025 13:41:18 +0000 (09:41 -0400)
committerChristian Brauner <brauner@kernel.org>
Fri, 9 May 2025 10:35:30 +0000 (12:35 +0200)
iomap_write_begin() returns a folio based on current pos and
remaining length in the iter, and each caller then trims the
pos/length to the given folio. Clean this up a bit and let
iomap_write_begin() return the trimmed range along with the folio.

Signed-off-by: Brian Foster <bfoster@redhat.com>
Link: https://lore.kernel.org/20250506134118.911396-7-bfoster@redhat.com
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Christian Brauner <brauner@kernel.org>
fs/iomap/buffered-io.c

index 86482b84825999fd66e0fcd9fa711826096a2cba..572446635c9a3f5aee9eecedf5e9a1fe3b261bae 100644 (file)
@@ -679,11 +679,12 @@ static int iomap_read_folio_sync(loff_t block_start, struct folio *folio,
        return submit_bio_wait(&bio);
 }
 
-static int __iomap_write_begin(const struct iomap_iter *iter, loff_t pos,
-               size_t len, struct folio *folio)
+static int __iomap_write_begin(const struct iomap_iter *iter, size_t len,
+               struct folio *folio)
 {
        const struct iomap *srcmap = iomap_iter_srcmap(iter);
        struct iomap_folio_state *ifs;
+       loff_t pos = iter->pos;
        loff_t block_size = i_blocksize(iter->inode);
        loff_t block_start = round_down(pos, block_size);
        loff_t block_end = round_up(pos + len, block_size);
@@ -794,15 +795,22 @@ static int iomap_write_begin_inline(const struct iomap_iter *iter,
        return iomap_read_inline_data(iter, folio);
 }
 
-static int iomap_write_begin(struct iomap_iter *iter, size_t len,
-               struct folio **foliop)
+/*
+ * Grab and prepare a folio for write based on iter state. Returns the folio,
+ * offset, and length. Callers can optionally pass a max length *plen,
+ * otherwise init to zero.
+ */
+static int iomap_write_begin(struct iomap_iter *iter, struct folio **foliop,
+               size_t *poffset, u64 *plen)
 {
        const struct iomap_folio_ops *folio_ops = iter->iomap.folio_ops;
        const struct iomap *srcmap = iomap_iter_srcmap(iter);
        loff_t pos = iter->pos;
+       u64 len = min_t(u64, SIZE_MAX, iomap_length(iter));
        struct folio *folio;
        int status = 0;
 
+       len = min_not_zero(len, *plen);
        BUG_ON(pos + len > iter->iomap.offset + iter->iomap.length);
        if (srcmap != &iter->iomap)
                BUG_ON(pos + len > srcmap->offset + srcmap->length);
@@ -834,20 +842,20 @@ static int iomap_write_begin(struct iomap_iter *iter, size_t len,
                }
        }
 
-       if (pos + len > folio_pos(folio) + folio_size(folio))
-               len = folio_pos(folio) + folio_size(folio) - pos;
+       pos = iomap_trim_folio_range(iter, folio, poffset, &len);
 
        if (srcmap->type == IOMAP_INLINE)
                status = iomap_write_begin_inline(iter, folio);
        else if (srcmap->flags & IOMAP_F_BUFFER_HEAD)
                status = __block_write_begin_int(folio, pos, len, NULL, srcmap);
        else
-               status = __iomap_write_begin(iter, pos, len, folio);
+               status = __iomap_write_begin(iter, len, folio);
 
        if (unlikely(status))
                goto out_unlock;
 
        *foliop = folio;
+       *plen = len;
        return 0;
 
 out_unlock:
@@ -968,7 +976,7 @@ retry:
                        break;
                }
 
-               status = iomap_write_begin(iter, bytes, &folio);
+               status = iomap_write_begin(iter, &folio, &offset, &bytes);
                if (unlikely(status)) {
                        iomap_write_failed(iter->inode, iter->pos, bytes);
                        break;
@@ -976,7 +984,7 @@ retry:
                if (iter->iomap.flags & IOMAP_F_STALE)
                        break;
 
-               pos = iomap_trim_folio_range(iter, folio, &offset, &bytes);
+               pos = iter->pos;
 
                if (mapping_writably_mapped(mapping))
                        flush_dcache_folio(folio);
@@ -1296,14 +1304,12 @@ static int iomap_unshare_iter(struct iomap_iter *iter)
                bool ret;
 
                bytes = min_t(u64, SIZE_MAX, bytes);
-               status = iomap_write_begin(iter, bytes, &folio);
+               status = iomap_write_begin(iter, &folio, &offset, &bytes);
                if (unlikely(status))
                        return status;
                if (iomap->flags & IOMAP_F_STALE)
                        break;
 
-               iomap_trim_folio_range(iter, folio, &offset, &bytes);
-
                ret = iomap_write_end(iter, bytes, bytes, folio);
                __iomap_put_folio(iter, bytes, folio);
                if (WARN_ON_ONCE(!ret))
@@ -1368,7 +1374,7 @@ static int iomap_zero_iter(struct iomap_iter *iter, bool *did_zero)
                bool ret;
 
                bytes = min_t(u64, SIZE_MAX, bytes);
-               status = iomap_write_begin(iter, bytes, &folio);
+               status = iomap_write_begin(iter, &folio, &offset, &bytes);
                if (status)
                        return status;
                if (iter->iomap.flags & IOMAP_F_STALE)
@@ -1377,7 +1383,6 @@ static int iomap_zero_iter(struct iomap_iter *iter, bool *did_zero)
                /* warn about zeroing folios beyond eof that won't write back */
                WARN_ON_ONCE(folio_pos(folio) > iter->inode->i_size);
 
-               iomap_trim_folio_range(iter, folio, &offset, &bytes);
                folio_zero_range(folio, offset, bytes);
                folio_mark_accessed(folio);