On 5/22/26 16:20, 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); > } > > + 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)) { > + 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,
ping _______________________________________________ Linux-f2fs-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
