[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