* [PATCH] iomap: don't update i_size of block devices on buffered write
@ 2026-11-13 15:02 Breno Leitao
0 siblings, 0 replies; only message in thread
From: Breno Leitao @ 2026-11-13 15:02 UTC (permalink / raw)
To: Christian Brauner, Jens Axboe, Hannes Reinecke, Pankaj Raghav,
Johannes Thumshirn
Cc: Luis Chamberlain, linux-xfs, linux-fsdevel, linux-kernel,
kernel-team, Breno Leitao
We are seeing this warning on an arm64 linux-next host while the ublk
selftests run (stress_01 deletes the ublk disks under fio buffered
writes):
WARNING: mm/truncate.c:902 at pagecache_isize_extended+0x37c/0x490, CPU#40: iou-wrk-3496756/3497370
Call trace:
pagecache_isize_extended+0x37c/0x490 (P)
iomap_file_buffered_write+0x38c/0x5d0
blkdev_buffered_write+0xcc/0x138
blkdev_write_iter+0x32c/0x4e0
io_write+0x77c/0xff8
The theory is that the disk shrank under the write. del_gendisk() sets
the capacity to 0, which writes the bdev inode's i_size under
bd_size_lock only. A writer whose mapping predates that reads
old_size == 0 in iomap_write_iter(), sets i_size to pos + written and
calls pagecache_isize_extended(inode, 0, pos). blkdev_buffered_write()
holds i_rwsem shared, so a writer at a lower offset can store a smaller
i_size in between, and WARN_ON(to > inode->i_size) fires. Even without
the warning, the write path regrows the size of a dead disk. The block
layer owns that size (bdev_set_nr_sectors()), and blkdev_write_end()
never touched it before the switch to iomap.
A reproducer on linux-next supports the theory: 128 threads doing 64K
buffered writes to a loop device, while another thread flips its
capacity between 1M and 1G with LOOP_SET_STATUS64, hit the warning 6
to 18 times per 30 second run (4 runs). With this patch it never fires,
and data written through the page cache still reads back intact.
Skip the size update and pagecache_isize_extended() for block devices.
Fixes: 487c607df790 ("block: use iomap for writes to block devices")
Signed-off-by: Breno Leitao <leitao@debian.org>
---
fs/iomap/buffered-io.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c
index 6d843b168d5f7d..3a171a70e6adde 100644
--- a/fs/iomap/buffered-io.c
+++ b/fs/iomap/buffered-io.c
@@ -1256,14 +1256,15 @@ static int iomap_write_iter(struct iomap_iter *iter, struct iov_iter *i,
* unlock and release the folio.
*/
old_size = iter->inode->i_size;
- if (pos + written > old_size &&
+ if (pos + written > old_size && !S_ISBLK(iter->inode->i_mode) &&
!(iter->iomap.flags & IOMAP_F_FSVERITY)) {
i_size_write(iter->inode, pos + written);
iter->iomap.flags |= IOMAP_F_SIZE_CHANGED;
}
__iomap_put_folio(iter, write_ops, written, folio);
- if (old_size < pos && !(iter->iomap.flags & IOMAP_F_FSVERITY))
+ if (old_size < pos && !S_ISBLK(iter->inode->i_mode) &&
+ !(iter->iomap.flags & IOMAP_F_FSVERITY))
pagecache_isize_extended(iter->inode, old_size, pos);
cond_resched();
---
base-commit: 6d582d78fad9d828e575ca0cdcff8ea47a77220b
change-id: 20261113-iomap-bdev-isize-a67166c971b7
Best regards,
--
Breno Leitao <leitao@debian.org>
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2026-11-13 15:03 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-13 15:02 [PATCH] iomap: don't update i_size of block devices on buffered write Breno Leitao
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®