* [PATCH] ext4: Fail unaligned direct IO write with EINVAL
@ 2025-09-01 11:27 Jan Kara
2025-09-02 1:35 ` Ritesh Harjani
2025-09-26 21:47 ` Theodore Ts'o
0 siblings, 2 replies; 3+ messages in thread
From: Jan Kara @ 2025-09-01 11:27 UTC (permalink / raw)
To: Ted Tso; +Cc: linux-ext4, Ritesh Harjani, Jan Kara
Commit bc264fea0f6f ("iomap: support incremental iomap_iter advances")
changed the error handling logic in iomap_iter(). Previously any error
from iomap_dio_bio_iter() got propagated to userspace, after this commit
if ->iomap_end returns error, it gets propagated to userspace instead of
an error from iomap_dio_bio_iter(). This results in unaligned writes to
ext4 to silently fallback to buffered IO instead of erroring out.
Now returning ENOTBLK for DIO writes from ext4_iomap_end() seems
unnecessary these days. It is enough to return ENOTBLK from
ext4_iomap_begin() when we don't support DIO write for that particular
file offset (due to hole).
Fixes: bc264fea0f6f ("iomap: support incremental iomap_iter advances")
Signed-off-by: Jan Kara <jack@suse.cz>
---
fs/ext4/inode.c | 35 -----------------------------------
1 file changed, 35 deletions(-)
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 5b7a15db4953..c3b23c90fd11 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -3872,47 +3872,12 @@ 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.43.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH] ext4: Fail unaligned direct IO write with EINVAL
2025-09-01 11:27 [PATCH] ext4: Fail unaligned direct IO write with EINVAL Jan Kara
@ 2025-09-02 1:35 ` Ritesh Harjani
2025-09-26 21:47 ` Theodore Ts'o
1 sibling, 0 replies; 3+ messages in thread
From: Ritesh Harjani @ 2025-09-02 1:35 UTC (permalink / raw)
To: Jan Kara, Ted Tso; +Cc: linux-ext4, Jan Kara
Jan Kara <jack@suse.cz> writes:
> Commit bc264fea0f6f ("iomap: support incremental iomap_iter advances")
> changed the error handling logic in iomap_iter(). Previously any error
> from iomap_dio_bio_iter() got propagated to userspace, after this commit
> if ->iomap_end returns error, it gets propagated to userspace instead of
> an error from iomap_dio_bio_iter(). This results in unaligned writes to
> ext4 to silently fallback to buffered IO instead of erroring out.
>
> Now returning ENOTBLK for DIO writes from ext4_iomap_end() seems
> unnecessary these days. It is enough to return ENOTBLK from
> ext4_iomap_begin() when we don't support DIO write for that particular
> file offset (due to hole).
>
> Fixes: bc264fea0f6f ("iomap: support incremental iomap_iter advances")
> Signed-off-by: Jan Kara <jack@suse.cz>
> ---
> fs/ext4/inode.c | 35 -----------------------------------
> 1 file changed, 35 deletions(-)
Thanks Jan for taking a deeper look and root causing that the problem
lay in iomap. I agree with the fix.
w.r.t Atomic DIO write:
Earlier we explicitely used to check (in ext4_want_directio_fallback())
if the write request was atomic, in that case we never want a fallback.
However that was mostly a safe guarding. As I looked into it we have
multiple checks at multiple places to safe guard atomic write DIO
request. ext4_iomap_alloc() for atomic writes ensures that allocation
always happens for the full requested length, IOMAP layer also ensures
that if the bio formed is not of the full user requested length then it
will return an error. We also have a WARN_ON_ONCE(1) in ext4 in-case if
we ever fallback to buffered-io for atomic DIO request.
So I believe we are good in this case.
The change looks good to me. So please feel free to add:
Reviewed-by: Ritesh Harjani (IBM) <ritesh.list@gmail.com>
>
> diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
> index 5b7a15db4953..c3b23c90fd11 100644
> --- a/fs/ext4/inode.c
> +++ b/fs/ext4/inode.c
> @@ -3872,47 +3872,12 @@ 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.43.0
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] ext4: Fail unaligned direct IO write with EINVAL
2025-09-01 11:27 [PATCH] ext4: Fail unaligned direct IO write with EINVAL Jan Kara
2025-09-02 1:35 ` Ritesh Harjani
@ 2025-09-26 21:47 ` Theodore Ts'o
1 sibling, 0 replies; 3+ messages in thread
From: Theodore Ts'o @ 2025-09-26 21:47 UTC (permalink / raw)
To: Jan Kara; +Cc: Theodore Ts'o, linux-ext4, Ritesh Harjani
On Mon, 01 Sep 2025 13:27:40 +0200, Jan Kara wrote:
> Commit bc264fea0f6f ("iomap: support incremental iomap_iter advances")
> changed the error handling logic in iomap_iter(). Previously any error
> from iomap_dio_bio_iter() got propagated to userspace, after this commit
> if ->iomap_end returns error, it gets propagated to userspace instead of
> an error from iomap_dio_bio_iter(). This results in unaligned writes to
> ext4 to silently fallback to buffered IO instead of erroring out.
>
> [...]
Applied, thanks!
[1/1] ext4: Fail unaligned direct IO write with EINVAL
commit: 963845748fe67125006859229487b45485564db7
Best regards,
--
Theodore Ts'o <tytso@mit.edu>
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2025-09-26 21:48 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-09-01 11:27 [PATCH] ext4: Fail unaligned direct IO write with EINVAL Jan Kara
2025-09-02 1:35 ` Ritesh Harjani
2025-09-26 21:47 ` Theodore Ts'o
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox