Re: [PATCH v2 1/3] btrfs: use aligned range for locking in extent_fiemap()
Filipe Manana <[email protected]> Tue, 28 Jul 2026 10:50:37 +0100
| Newsgroups | org.kernel.vger.linux-btrfs |
|---|---|
| Message-ID | <CAL3q7H6hB6n5NOaxgaj=8Ddp9A3UGsnKcJ3vHeOJ+UftU+Jkmg@mail.gmail.com> |
On Tue, Jul 28, 2026 at 10:41 AM Qu Wenruo <[email protected]> wrote: > > > > 在 2026/7/28 19:08, Filipe Manana 写道: > > On Tue, Jul 28, 2026 at 10:23 AM 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 an exclusive end into > >> btrfs_lock_extent(), which will step into the next block unexpectedly. > >> > >> Fix @range_end to be inclusive, so that btrfs_lock_extent() and > >> btrfs_unlock_extent() will lock/unlock the correct aligned range. > >> > >> 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 the problem is passing an exclusive end to btrfs_lock_extent(), > > then rather than doing all these changes to this variables, which is > > error prone since they are used in several places and generally we use > > exclusive ends everywhere, I'd prefer to simply change the call to > > btrfs_lock_extent() and btrfs_unlock_extent() to receive 'range_end - > > 1'. That also makes the fix much clearer. > > Thanks for the advice, indeed that is much safer. After that you can add: Reviewed-by: Filipe Manana <[email protected]> Thanks. > > Thanks, > Qu> > > Thanks. > > > >> } > >> > >> if (cache.cached && cache.offset + cache.len >= last_extent_end) { > >> -- > >> 2.54.0 > >> > >> >