Unverified Commit 6a96fb65 authored by Darrick J. Wong's avatar Darrick J. Wong Committed by Christian Brauner
Browse files

iomap: error out on file IO when there is no inline_data buffer



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: default avatarDarrick J. Wong <djwong@kernel.org>
Link: https://lore.kernel.org/175803480324.966383.7414345025943296442.stgit@frogsfrogsfrogs


Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarChristian Brauner <brauner@kernel.org>
parent 231af8c1
Loading
Loading
Loading
Loading
+10 −5
Original line number Diff line number Diff line
@@ -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;
+3 −0
Original line number Diff line number Diff line
@@ -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;