Re: [PATCH 2/3] iomap: don't lose a fiemap iteration error when emitting the last extent
From: Darrick J. Wong
Date: Mon Sep 21 2026 - 18:38:29 EST
On Mon, Sep 21, 2026 at 10:31:32AM +0200, Andrea Parri wrote:
> iomap_fiemap() emits extents one behind: iomap_fiemap_iter() flushes the
> previous extent and remembers the current one, and the remembered extent
> is written with FIEMAP_EXTENT_LAST after the iteration loop.
>
> That final flush overwrites ret, so when ->iomap_begin() fails partway
> through the iteration the error is replaced by the result of
> iomap_to_fiemap() (zero on success) and iomap_fiemap() returns success
> with a truncated extent list whose last entry is wrongly marked as the
> last extent in the file. The pre-iomap_iter code returned the error
> from inside the loop, before flushing the pending extent.
>
> Check for the iteration error before flushing the pending extent, so
> that real errors are propagated and only a successful iteration emits
> the final FIEMAP_EXTENT_LAST extent. -ENOENT (no mapping) is still not
> an error, and the pending extent is still emitted in that case.
>
> Fixes: 7892386d35715 ("iomap: switch iomap_fiemap to use iomap_iter")
> Cc: stable@xxxxxxxxxxxxxxx
Oooh, an oldie!
Cc: <stable@xxxxxxxxxxxxxxx> # v5.15
> Assisted-by: LLM
> Signed-off-by: Andrea Parri <parri.andrea@xxxxxxxxx>
Reviewed-by: "Darrick J. Wong" <djwong@xxxxxxxxxx>
--D
> ---
> fs/iomap/fiemap.c | 8 ++++----
> 1 file changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/fs/iomap/fiemap.c b/fs/iomap/fiemap.c
> index d11dadff82865..54b824b7edb5c 100644
> --- a/fs/iomap/fiemap.c
> +++ b/fs/iomap/fiemap.c
> @@ -76,15 +76,15 @@ int iomap_fiemap(struct inode *inode, struct fiemap_extent_info *fi,
> while ((ret = iomap_iter(&iter, ops)) > 0)
> iter.status = iomap_fiemap_iter(&iter, fi, &prev);
>
> + /* inode with no (attribute) mapping will give ENOENT */
> + if (ret < 0 && ret != -ENOENT)
> + return ret;
> +
> if (prev.type != IOMAP_HOLE) {
> ret = iomap_to_fiemap(fi, &prev, FIEMAP_EXTENT_LAST);
> if (ret < 0)
> return ret;
> }
> -
> - /* inode with no (attribute) mapping will give ENOENT */
> - if (ret < 0 && ret != -ENOENT)
> - return ret;
> return 0;
> }
> EXPORT_SYMBOL_GPL(iomap_fiemap);
> --
> 2.53.0
>