[SRU][Q][PATCH 1/1] UBUNTU: SAUCE: Revert "ext4: fail unaligned direct IO write with EINVAL"

Edoardo Canepa edoardo.canepa at canonical.com
Thu Jan 8 10:25:41 UTC 2026


BugLink: https://bugs.launchpad.net/bugs/2137698

This reverts commit 6c840c16c7cc0d3464ebf4a6d4c4f03763a45ff0.

This commit was pulled from stable upstream 6.17.4, however makes the
ubuntu_blktrace_smoke_test fail as reported in the launchpad bug
when performed by rust coreutils

Signed-off-by: Edoardo Canepa <edoardo.canepa at canonical.com>
---
 fs/ext4/inode.c | 35 +++++++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index f9e4ac87211e..79422c6f664c 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -3872,12 +3872,47 @@ static int ext4_iomap_overwrite_begin(struct inode *inode, loff_t offset,
 	return ret;
 }
 
+static inline bool ext4_want_directio_fallback(unsigned flags, ssize_t written)
+{
+	/* must be a directio to fall back to buffered */
+	if ((flags & (IOMAP_WRITE | IOMAP_DIRECT)) !=
+		    (IOMAP_WRITE | IOMAP_DIRECT))
+		return false;
+
+	/* atomic writes are all-or-nothing */
+	if (flags & IOMAP_ATOMIC)
+		return false;
+
+	/* can only try again if we wrote nothing */
+	return written == 0;
+}
+
+static int ext4_iomap_end(struct inode *inode, loff_t offset, loff_t length,
+			  ssize_t written, unsigned flags, struct iomap *iomap)
+{
+	/*
+	 * Check to see whether an error occurred while writing out the data to
+	 * the allocated blocks. If so, return the magic error code for
+	 * non-atomic write so that we fallback to buffered I/O and attempt to
+	 * complete the remainder of the I/O.
+	 * For non-atomic writes, any blocks that may have been
+	 * allocated in preparation for the direct I/O will be reused during
+	 * buffered I/O. For atomic write, we never fallback to buffered-io.
+	 */
+	if (ext4_want_directio_fallback(flags, written))
+		return -ENOTBLK;
+
+	return 0;
+}
+
 const struct iomap_ops ext4_iomap_ops = {
 	.iomap_begin		= ext4_iomap_begin,
+	.iomap_end		= ext4_iomap_end,
 };
 
 const struct iomap_ops ext4_iomap_overwrite_ops = {
 	.iomap_begin		= ext4_iomap_overwrite_begin,
+	.iomap_end		= ext4_iomap_end,
 };
 
 static int ext4_iomap_begin_report(struct inode *inode, loff_t offset,
-- 
2.51.0




More information about the kernel-team mailing list