From 9fd1afea19fa7c4ba438a1d162739e0832073a4c Mon Sep 17 00:00:00 2001 From: Tal Zussman Date: Fri, 9 Oct 2026 12:50:14 -0400 Subject: [PATCH] block: don't fall back to buffered I/O for atomic writes blkdev_direct_write() turns an -EBUSY from page cache invalidation into a 0 return, so an IOCB_ATOMIC write is retried in full through blkdev_buffered_write(), with no atomicity guarantee. Skip the buffered fallback in blkdev_write_iter() for IOCB_ATOMIC, as it already does for IOCB_NOWAIT, so the -EBUSY case returns -EAGAIN and the caller retries, matching __iomap_dio_rw(). ext4 has the same fallback and only warns in it. For block devices the fallback can be skipped before any I/O is submitted, so fail early instead. Fixes: caf336f81b3a ("block: Add fops atomic write support") Reported-by: Sashiko Link: https://sashiko.dev/#/patchset/20260802-blkdev-fixes-v1-0-a82fc549fd74%40columbia.edu?part=2 Assisted-by: Claude:claude-fable-5 Reviewed-by: Hannes Reinecke Reviewed-by: John Garry Signed-off-by: Tal Zussman Link: https://patch.msgid.link/20261009-blkdev-fixes-v6-6-307939c387df@columbia.edu Signed-off-by: Jens Axboe --- block/fops.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/block/fops.c b/block/fops.c index 1ac3fa285090..41fa0c663f77 100644 --- a/block/fops.c +++ b/block/fops.c @@ -782,10 +782,11 @@ static ssize_t blkdev_write_iter(struct kiocb *iocb, struct iov_iter *from) if (iocb->ki_flags & IOCB_DIRECT) { ret = blkdev_direct_write(iocb, from); if (ret >= 0 && iov_iter_count(from)) { - if (iocb->ki_flags & IOCB_NOWAIT) { + if (iocb->ki_flags & (IOCB_NOWAIT | IOCB_ATOMIC)) { /* * The buffered fallback blocks on i_rwsem and - * on writeback of the data it copied: return + * on writeback of the data it copied, and + * can't provide torn-write protection: return * the short direct write instead and let the * caller retry. The bytes already written * still need a flush if REQ_FUA was not set.