mirror of https://github.com/torvalds/linux.git
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: 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>
This commit is contained in:
parent
231af8c14f
commit
6a96fb653b
|
|
@ -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 size = i_size_read(iter->inode) - iomap->offset;
|
||||||
size_t offset = offset_in_folio(folio, 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))
|
if (folio_test_uptodate(folio))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
@ -894,7 +897,7 @@ static bool __iomap_write_end(struct inode *inode, loff_t pos, size_t len,
|
||||||
return true;
|
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)
|
struct folio *folio, loff_t pos, size_t copied)
|
||||||
{
|
{
|
||||||
const struct iomap *iomap = &iter->iomap;
|
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));
|
WARN_ON_ONCE(!folio_test_uptodate(folio));
|
||||||
BUG_ON(!iomap_inline_data_valid(iomap));
|
BUG_ON(!iomap_inline_data_valid(iomap));
|
||||||
|
|
||||||
|
if (WARN_ON_ONCE(!iomap->inline_data))
|
||||||
|
return false;
|
||||||
|
|
||||||
flush_dcache_folio(folio);
|
flush_dcache_folio(folio);
|
||||||
addr = kmap_local_folio(folio, pos);
|
addr = kmap_local_folio(folio, pos);
|
||||||
memcpy(iomap_inline_data(iomap, pos), addr, copied);
|
memcpy(iomap_inline_data(iomap, pos), addr, copied);
|
||||||
kunmap_local(addr);
|
kunmap_local(addr);
|
||||||
|
|
||||||
mark_inode_dirty(iter->inode);
|
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);
|
const struct iomap *srcmap = iomap_iter_srcmap(iter);
|
||||||
loff_t pos = iter->pos;
|
loff_t pos = iter->pos;
|
||||||
|
|
||||||
if (srcmap->type == IOMAP_INLINE) {
|
if (srcmap->type == IOMAP_INLINE)
|
||||||
iomap_write_end_inline(iter, folio, pos, copied);
|
return iomap_write_end_inline(iter, folio, pos, copied);
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (srcmap->flags & IOMAP_F_BUFFER_HEAD) {
|
if (srcmap->flags & IOMAP_F_BUFFER_HEAD) {
|
||||||
size_t bh_written;
|
size_t bh_written;
|
||||||
|
|
|
||||||
|
|
@ -519,6 +519,9 @@ static int iomap_dio_inline_iter(struct iomap_iter *iomi, struct iomap_dio *dio)
|
||||||
loff_t pos = iomi->pos;
|
loff_t pos = iomi->pos;
|
||||||
u64 copied;
|
u64 copied;
|
||||||
|
|
||||||
|
if (WARN_ON_ONCE(!inline_data))
|
||||||
|
return -EIO;
|
||||||
|
|
||||||
if (WARN_ON_ONCE(!iomap_inline_data_valid(iomap)))
|
if (WARN_ON_ONCE(!iomap_inline_data_valid(iomap)))
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue