Re: [PATCH 1/2] btrfs: use proper inclusive end in extent_fiemap()
Qu Wenruo <[email protected]> Tue, 28 Jul 2026 18:50:01 +0930
| Newsgroups | org.kernel.vger.linux-btrfs |
|---|---|
| Message-ID | <[email protected]> |
在 2026/7/28 18:47, Daniel Vacek 写道: > On Tue, 28 Jul 2026 at 10:40, Qu Wenruo <[email protected]> wrote: >> 在 2026/7/28 17:35, Daniel Vacek 写道: >>> On Tue, 28 Jul 2026 at 08:46, Qu Wenruo <[email protected]> wrote: >>>> The @end parameter for all extent io tree helpers is inclusive, but >>>> the call site in extent_fiemap() is passing exclusive end. >>>> >>>> Fix it to follow the common pattern. >>>> >>>> Fixes: ac3c0d36a2a2 ("btrfs: make fiemap more efficient and accurate reporting extent sharedness") >>>> Signed-off-by: Qu Wenruo <[email protected]> >>>> --- >>>> fs/btrfs/fiemap.c | 8 ++++---- >>>> 1 file changed, 4 insertions(+), 4 deletions(-) >>>> >>>> diff --git a/fs/btrfs/fiemap.c b/fs/btrfs/fiemap.c >>>> index ba6a360074c0..2f2ae0b76799 100644 >>>> --- a/fs/btrfs/fiemap.c >>>> +++ b/fs/btrfs/fiemap.c >>>> @@ -657,7 +657,7 @@ static int extent_fiemap(struct btrfs_inode *inode, >>>> >>>> restart: >>>> range_start = round_down(start, sectorsize); >>>> - range_end = round_up(start + len, sectorsize); >>>> + range_end = round_up(start + len, sectorsize) - 1; >>>> prev_extent_end = range_start; >>>> >>>> btrfs_lock_extent(&inode->io_tree, range_start, range_end, &cached_state); >>>> @@ -710,7 +710,7 @@ static int extent_fiemap(struct btrfs_inode *inode, >>>> >>>> /* We have in implicit hole (NO_HOLES feature enabled). */ >>>> if (prev_extent_end < key.offset) { >>>> - const u64 hole_end = min(key.offset, range_end) - 1; >>>> + const u64 hole_end = min(key.offset - 1, range_end); >>>> >>>> ret = fiemap_process_hole(inode, fieinfo, &cache, >>>> &delalloc_cached_state, >>>> @@ -812,10 +812,10 @@ static int extent_fiemap(struct btrfs_inode *inode, >>>> if (!stopped && prev_extent_end < range_end) { >>>> ret = fiemap_process_hole(inode, fieinfo, &cache, >>>> &delalloc_cached_state, backref_ctx, >>>> - 0, 0, 0, prev_extent_end, range_end - 1); >>>> + 0, 0, 0, prev_extent_end, range_end); >>>> if (ret < 0) >>>> goto out_unlock; >>>> - prev_extent_end = range_end; >>>> + prev_extent_end = range_end + 1; >>>> } >>>> >>>> if (cache.cached && cache.offset + cache.len >= last_extent_end) { >>>> -- >>>> 2.54.0 >>> >>> I don't really get why you left out these: >>> >>> @@ -680,7 +680,7 @@ static int extent_fiemap(struct btrfs_inode *inode, >>> goto check_eof_delalloc; >>> } >>> >>> - while (prev_extent_end < range_end) { >>> + while (prev_extent_end <= range_end) { >>> struct extent_buffer *leaf = path->nodes[0]; >>> struct btrfs_file_extent_item *ei; >>> struct btrfs_key key; >>> @@ -809,13 +809,13 @@ static int extent_fiemap(struct btrfs_inode *inode, >>> } >>> >>> check_eof_delalloc: >>> - if (!stopped && prev_extent_end < range_end) { >>> + if (!stopped && prev_extent_end <= range_end) { >>> ret = fiemap_process_hole(inode, fieinfo, &cache, >>> &delalloc_cached_state, backref_ctx, >>> >>> Am I missing something? >> >> Because we won't reach the == case at all. >> >> The start is always increased by a value aligned to sectorsize. > > I understand round_down() possibly decreases not increases. So if > start and start + len - 1 fall into the same block you get the == > case. Am I wrong? The only case when that happen is when @len is 0, which is already rejected by fiemap_prep() > >> For inclusive range_end, we either completely pass it by 1, or smaller >> than it. >> >> So that "==" will never be hit.> >>> --nX >>