On 6/12/26 19:58, Yongpeng Yang wrote:
> From: Yongpeng Yang <[email protected]>
> 
> The following scenario can cause fiemap to report incorrect extents:
> 
> $ mkfs.f2fs /dev/vdb -f
> $ mount -o mode=lfs /dev/vdb /mnt/f2fs/
> $ dd if=/dev/urandom of=data bs=4K count=874 conv=notrunc
> $ f2fs_io fiemap 0 1000000 data 1
> $ shrink all extent
> $ dd if=/dev/urandom of=data bs=4K count=150 seek=874 conv=notrunc
> $ f2fs_io fiemap 0 1000000 data 1
> Fiemap: offset = 0 len = 1000000
>         logical addr.    physical addr.   length           flags
> 0       0000000000000000 00000002868d4000 000000000036a000 00001000
> 1       000000000036a000 0000000286c3e000 0000000000096000 00001001
> 
> The root cause is that when the largest extent is not in the extent
> tree, mergeable extents are not merged, causing f2fs_map_blocks to
> misjudge and output an incorrect extent list.
> 
> Fix this by allowing the extent being inserted to merge with the largest
> extent. When updating the extent tree range, if the new extent can be
> front-merged or back-merged with the largest extent and the largest
> extent is not in the rb-tree, merge them before the normal lookup.
> 
> Fixes: 429511cdf8b3 ("f2fs: add core functions for rb-tree extent cache")
> Signed-off-by: Yongpeng Yang <[email protected]>
> ---
>  fs/f2fs/extent_cache.c | 21 +++++++++++++++++++++
>  1 file changed, 21 insertions(+)
> 
> diff --git a/fs/f2fs/extent_cache.c b/fs/f2fs/extent_cache.c
> index 61f6b9714366..aa368a01b035 100644
> --- a/fs/f2fs/extent_cache.c
> +++ b/fs/f2fs/extent_cache.c
> @@ -702,6 +702,27 @@ static void __update_extent_tree_range(struct inode 
> *inode,
>               __drop_largest_extent(et, fofs, len);
>       }
>  

This can only be used for EX_READ?

> +     if (et->largest.len != 0 &&
> +                     (__is_front_mergeable(tei, &et->largest, type) ||
> +                      __is_back_mergeable(tei, &et->largest, type))) {
> +             /* 0. try to merge with largest extent. */
> +             en = __lookup_extent_node_ret(&et->root,
> +                             et->cached_en, et->largest.fofs,
> +                             &prev_en, &next_en,
> +                             &insert_p, &insert_parent,
> +                             &leftmost);
> +             if (!en) {
> +                     if (__is_back_mergeable(tei, &et->largest, type)) {

Can we reuse result of previous __is_back_mergeable()?

Thanks,

> +                             tei->fofs = et->largest.fofs;
> +                             tei->blk = et->largest.blk;
> +                             fofs = tei->fofs;
> +                     }
> +                     tei->len += et->largest.len;
> +                     len = tei->len;
> +                     end = fofs + len;
> +             }
> +     }
> +
>       /* 1. lookup first extent node in range [fofs, fofs + len - 1] */
>       en = __lookup_extent_node_ret(&et->root,
>                                       et->cached_en, fofs,



_______________________________________________
Linux-f2fs-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

Reply via email to