]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
iomap: error out on file IO when there is no inline_data buffer
authorDarrick J. Wong <djwong@kernel.org>
Tue, 16 Sep 2025 15:00:45 +0000 (08:00 -0700)
committerChristian Brauner <brauner@kernel.org>
Fri, 19 Sep 2025 12:17:11 +0000 (14:17 +0200)
Return IO errors if an ->iomap_begin implementation returns an
IOMAP_INLINE buffer but forgets to set the inline_data pointer.
Filesystems should never do this, but we could help fs developers (me)
fix their bugs by handling this more gracefully than crashing the
kernel.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Link: https://lore.kernel.org/175803480324.966383.7414345025943296442.stgit@frogsfrogsfrogs
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Christian Brauner <brauner@kernel.org>
fs/iomap/buffered-io.c
fs/iomap/direct-io.c

index ed7dd6426b0eece158f77ddac245f49e29133be2..8b847a1e27f13eba67eb306a1d648ea2e19e587b 100644 (file)
@@ -304,6 +304,9 @@ static int iomap_read_inline_data(const struct iomap_iter *iter,
        size_t size = i_size_read(iter->inode) - iomap->offset;
        size_t offset = offset_in_folio(folio, iomap->offset);
 
+       if (WARN_ON_ONCE(!iomap->inline_data))
+               return -EIO;
+
        if (folio_test_uptodate(folio))
                return 0;
 
@@ -894,7 +897,7 @@ static bool __iomap_write_end(struct inode *inode, loff_t pos, size_t len,
        return true;
 }
 
-static void iomap_write_end_inline(const struct iomap_iter *iter,
+static bool iomap_write_end_inline(const struct iomap_iter *iter,
                struct folio *folio, loff_t pos, size_t copied)
 {
        const struct iomap *iomap = &iter->iomap;
@@ -903,12 +906,16 @@ static void iomap_write_end_inline(const struct iomap_iter *iter,
        WARN_ON_ONCE(!folio_test_uptodate(folio));
        BUG_ON(!iomap_inline_data_valid(iomap));
 
+       if (WARN_ON_ONCE(!iomap->inline_data))
+               return false;
+
        flush_dcache_folio(folio);
        addr = kmap_local_folio(folio, pos);
        memcpy(iomap_inline_data(iomap, pos), addr, copied);
        kunmap_local(addr);
 
        mark_inode_dirty(iter->inode);
+       return true;
 }
 
 /*
@@ -921,10 +928,8 @@ static bool iomap_write_end(struct iomap_iter *iter, size_t len, size_t copied,
        const struct iomap *srcmap = iomap_iter_srcmap(iter);
        loff_t pos = iter->pos;
 
-       if (srcmap->type == IOMAP_INLINE) {
-               iomap_write_end_inline(iter, folio, pos, copied);
-               return true;
-       }
+       if (srcmap->type == IOMAP_INLINE)
+               return iomap_write_end_inline(iter, folio, pos, copied);
 
        if (srcmap->flags & IOMAP_F_BUFFER_HEAD) {
                size_t bh_written;
index 6f25d4cfea9f7ee14dac511fac3a3ee3be9d3466..836f082651e52f051bbd2e39b0bf418a196ff511 100644 (file)
@@ -519,6 +519,9 @@ static int iomap_dio_inline_iter(struct iomap_iter *iomi, struct iomap_dio *dio)
        loff_t pos = iomi->pos;
        u64 copied;
 
+       if (WARN_ON_ONCE(!inline_data))
+               return -EIO;
+
        if (WARN_ON_ONCE(!iomap_inline_data_valid(iomap)))
                return -EIO;