Re: [f2fs-dev] [PATCH RESEND 1/5] f2fs: fix extent merge failure when largest extent is not in rb-tree
Chao Yu via Linux-f2fs-devel <[email protected]>
| Newsgroups | net.sourceforge.lists.linux-f2fs-devel |
|---|---|
| Message-ID | <[email protected]> |
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