Skip to content

Commit 09f7618

Browse files
adam900710kdave
authored andcommitted
btrfs: scrub: factor out parity scrub code into a helper
The function scrub_raid56_parity_stripe() is handling the parity stripe by the following steps: - Scrub each data stripes And make sure everything is fine in each data stripe - Cache the data stripe into the raid bio - Use the cached raid bio to scrub the target parity stripe Extract the last two steps into a new helper, scrub_raid56_cached_parity(), as a cleanup and make the error handling more straightforward. With the following minor cleanups: - Use on-stack bio structure The bio is always empty thus we do not need any bio vector nor the block device. Thus there is no need to allocate a bio, the on-stack one is more than enough to cut it. - Remove the unnecessary btrfs_put_bioc() call if btrfs_map_block() failed If btrfs_map_block() is failed, @bioc_ret will not be touched thus there is no need to call btrfs_put_bioc() in this case. - Use a proper out: tag to do the cleanup Now the error cleanup is much shorter and simpler, just btrfs_bio_counter_dec() and bio_uninit(). Signed-off-by: Qu Wenruo <wqu@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
1 parent af1b43e commit 09f7618

File tree

1 file changed

+52
-41
lines changed

1 file changed

+52
-41
lines changed

fs/btrfs/scrub.c

Lines changed: 52 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -2113,24 +2113,69 @@ static int should_cancel_scrub(const struct scrub_ctx *sctx)
21132113
return 0;
21142114
}
21152115

2116+
static int scrub_raid56_cached_parity(struct scrub_ctx *sctx,
2117+
struct btrfs_device *scrub_dev,
2118+
struct btrfs_chunk_map *map,
2119+
u64 full_stripe_start,
2120+
unsigned long *extent_bitmap)
2121+
{
2122+
DECLARE_COMPLETION_ONSTACK(io_done);
2123+
struct btrfs_fs_info *fs_info = sctx->fs_info;
2124+
struct btrfs_io_context *bioc = NULL;
2125+
struct btrfs_raid_bio *rbio;
2126+
struct bio bio;
2127+
const int data_stripes = nr_data_stripes(map);
2128+
u64 length = btrfs_stripe_nr_to_offset(data_stripes);
2129+
int ret;
2130+
2131+
bio_init(&bio, NULL, NULL, 0, REQ_OP_READ);
2132+
bio.bi_iter.bi_sector = full_stripe_start >> SECTOR_SHIFT;
2133+
bio.bi_private = &io_done;
2134+
bio.bi_end_io = raid56_scrub_wait_endio;
2135+
2136+
btrfs_bio_counter_inc_blocked(fs_info);
2137+
ret = btrfs_map_block(fs_info, BTRFS_MAP_WRITE, full_stripe_start,
2138+
&length, &bioc, NULL, NULL);
2139+
if (ret < 0)
2140+
goto out;
2141+
/* For RAID56 write there must be an @bioc allocated. */
2142+
ASSERT(bioc);
2143+
rbio = raid56_parity_alloc_scrub_rbio(&bio, bioc, scrub_dev, extent_bitmap,
2144+
BTRFS_STRIPE_LEN >> fs_info->sectorsize_bits);
2145+
btrfs_put_bioc(bioc);
2146+
if (!rbio) {
2147+
ret = -ENOMEM;
2148+
goto out;
2149+
}
2150+
/* Use the recovered stripes as cache to avoid read them from disk again. */
2151+
for (int i = 0; i < data_stripes; i++) {
2152+
struct scrub_stripe *stripe = &sctx->raid56_data_stripes[i];
2153+
2154+
raid56_parity_cache_data_folios(rbio, stripe->folios,
2155+
full_stripe_start + (i << BTRFS_STRIPE_LEN_SHIFT));
2156+
}
2157+
raid56_parity_submit_scrub_rbio(rbio);
2158+
wait_for_completion_io(&io_done);
2159+
ret = blk_status_to_errno(bio.bi_status);
2160+
out:
2161+
btrfs_bio_counter_dec(fs_info);
2162+
bio_uninit(&bio);
2163+
return ret;
2164+
}
2165+
21162166
static int scrub_raid56_parity_stripe(struct scrub_ctx *sctx,
21172167
struct btrfs_device *scrub_dev,
21182168
struct btrfs_block_group *bg,
21192169
struct btrfs_chunk_map *map,
21202170
u64 full_stripe_start)
21212171
{
2122-
DECLARE_COMPLETION_ONSTACK(io_done);
21232172
struct btrfs_fs_info *fs_info = sctx->fs_info;
2124-
struct btrfs_raid_bio *rbio;
2125-
struct btrfs_io_context *bioc = NULL;
21262173
struct btrfs_path extent_path = { 0 };
21272174
struct btrfs_path csum_path = { 0 };
2128-
struct bio *bio;
21292175
struct scrub_stripe *stripe;
21302176
bool all_empty = true;
21312177
const int data_stripes = nr_data_stripes(map);
21322178
unsigned long extent_bitmap = 0;
2133-
u64 length = btrfs_stripe_nr_to_offset(data_stripes);
21342179
int ret;
21352180

21362181
ASSERT(sctx->raid56_data_stripes);
@@ -2252,42 +2297,8 @@ static int scrub_raid56_parity_stripe(struct scrub_ctx *sctx,
22522297
}
22532298

22542299
/* Now we can check and regenerate the P/Q stripe. */
2255-
bio = bio_alloc(NULL, 1, REQ_OP_READ, GFP_NOFS);
2256-
bio->bi_iter.bi_sector = full_stripe_start >> SECTOR_SHIFT;
2257-
bio->bi_private = &io_done;
2258-
bio->bi_end_io = raid56_scrub_wait_endio;
2259-
2260-
btrfs_bio_counter_inc_blocked(fs_info);
2261-
ret = btrfs_map_block(fs_info, BTRFS_MAP_WRITE, full_stripe_start,
2262-
&length, &bioc, NULL, NULL);
2263-
if (ret < 0) {
2264-
bio_put(bio);
2265-
btrfs_put_bioc(bioc);
2266-
btrfs_bio_counter_dec(fs_info);
2267-
goto out;
2268-
}
2269-
rbio = raid56_parity_alloc_scrub_rbio(bio, bioc, scrub_dev, &extent_bitmap,
2270-
BTRFS_STRIPE_LEN >> fs_info->sectorsize_bits);
2271-
btrfs_put_bioc(bioc);
2272-
if (!rbio) {
2273-
ret = -ENOMEM;
2274-
bio_put(bio);
2275-
btrfs_bio_counter_dec(fs_info);
2276-
goto out;
2277-
}
2278-
/* Use the recovered stripes as cache to avoid read them from disk again. */
2279-
for (int i = 0; i < data_stripes; i++) {
2280-
stripe = &sctx->raid56_data_stripes[i];
2281-
2282-
raid56_parity_cache_data_folios(rbio, stripe->folios,
2283-
full_stripe_start + (i << BTRFS_STRIPE_LEN_SHIFT));
2284-
}
2285-
raid56_parity_submit_scrub_rbio(rbio);
2286-
wait_for_completion_io(&io_done);
2287-
ret = blk_status_to_errno(bio->bi_status);
2288-
bio_put(bio);
2289-
btrfs_bio_counter_dec(fs_info);
2290-
2300+
ret = scrub_raid56_cached_parity(sctx, scrub_dev, map, full_stripe_start,
2301+
&extent_bitmap);
22912302
out:
22922303
btrfs_release_path(&extent_path);
22932304
btrfs_release_path(&csum_path);

0 commit comments

Comments
 (0)