]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
btrfs: make sure extent and csum paths are always released in scrub_raid56_parity_str...
authorQu Wenruo <wqu@suse.com>
Wed, 5 Nov 2025 09:58:12 +0000 (20:28 +1030)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 18 Dec 2025 13:03:16 +0000 (14:03 +0100)
[ Upstream commit d435c513652e6a90a13c881986a2cc6420c99cab ]

Unlike queue_scrub_stripe() which uses the global sctx->extent_path and
sctx->csum_path which are always released at the end of scrub_stripe(),
scrub_raid56_parity_stripe() uses local extent_path and csum_path, as
that function is going to handle the full stripe, whose bytenr may be
smaller than the bytenr in the global sctx paths.

However the cleanup of local extent/csum paths is only happening after
we have successfully submitted an rbio.

There are several error routes that we didn't release those two paths:

- scrub_find_fill_first_stripe() errored out at csum tree search
  In that case extent_path is still valid, and that function itself will
  not release the extent_path passed in.
  And the function returns directly without releasing both paths.

- The full stripe is empty
- Some blocks failed to be recovered
- btrfs_map_block() failed
- raid56_parity_alloc_scrub_rbio() failed
  The function returns directly without releasing both paths.

Fix it by covering btrfs_release_path() calls inside the out: tag.

This is just a hot fix, in the long run we will go scoped based auto
freeing for both local paths.

Fixes: 1dc4888e725d ("btrfs: scrub: avoid unnecessary extent tree search preparing stripes")
Fixes: 3c771c194402 ("btrfs: scrub: avoid unnecessary csum tree search preparing stripes")
Signed-off-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
fs/btrfs/scrub.c

index ba20d9286a340cb671fe94e5b2b43a33c50f0521..65361af30234369ff32217ee1706ac5340f4cd81 100644 (file)
@@ -2230,9 +2230,9 @@ static int scrub_raid56_parity_stripe(struct scrub_ctx *sctx,
        bio_put(bio);
        btrfs_bio_counter_dec(fs_info);
 
+out:
        btrfs_release_path(&extent_path);
        btrfs_release_path(&csum_path);
-out:
        return ret;
 }