Commit 4fe44f9d authored by Qu Wenruo's avatar Qu Wenruo Committed by David Sterba

btrfs: scrub: move write back of repaired sectors to scrub_stripe_read_repair_worker()

Currently the scrub_stripe_read_repair_worker() only does reads to
rebuild the corrupted sectors, it doesn't do any writeback.

The design is mostly to put writeback into a more ordered manner, to
co-operate with dev-replace with zoned mode, which requires every write
to be submitted in their bytenr order.

However the writeback for repaired sectors into the original mirror
doesn't need such strong sync requirement, as it can only happen for
non-zoned devices.

This patch would move the writeback for repaired sectors into
scrub_stripe_read_repair_worker(), which removes two calls sites for
repaired sectors writeback. (one from flush_scrub_stripes(), one from
scrub_raid56_parity_stripe())
Signed-off-by: default avatarQu Wenruo <wqu@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent 39dc7bd9
...@@ -990,6 +990,9 @@ static void scrub_stripe_report_errors(struct scrub_ctx *sctx, ...@@ -990,6 +990,9 @@ static void scrub_stripe_report_errors(struct scrub_ctx *sctx,
spin_unlock(&sctx->stat_lock); spin_unlock(&sctx->stat_lock);
} }
static void scrub_write_sectors(struct scrub_ctx *sctx, struct scrub_stripe *stripe,
unsigned long write_bitmap, bool dev_replace);
/* /*
* The main entrance for all read related scrub work, including: * The main entrance for all read related scrub work, including:
* *
...@@ -998,13 +1001,16 @@ static void scrub_stripe_report_errors(struct scrub_ctx *sctx, ...@@ -998,13 +1001,16 @@ static void scrub_stripe_report_errors(struct scrub_ctx *sctx,
* - Go through the remaining mirrors and try to read as large blocksize as * - Go through the remaining mirrors and try to read as large blocksize as
* possible * possible
* - Go through all mirrors (including the failed mirror) sector-by-sector * - Go through all mirrors (including the failed mirror) sector-by-sector
* - Submit writeback for repaired sectors
* *
* Writeback does not happen here, it needs extra synchronization. * Writeback for dev-replace does not happen here, it needs extra
* synchronization for zoned devices.
*/ */
static void scrub_stripe_read_repair_worker(struct work_struct *work) static void scrub_stripe_read_repair_worker(struct work_struct *work)
{ {
struct scrub_stripe *stripe = container_of(work, struct scrub_stripe, work); struct scrub_stripe *stripe = container_of(work, struct scrub_stripe, work);
struct btrfs_fs_info *fs_info = stripe->bg->fs_info; struct scrub_ctx *sctx = stripe->sctx;
struct btrfs_fs_info *fs_info = sctx->fs_info;
int num_copies = btrfs_num_copies(fs_info, stripe->bg->start, int num_copies = btrfs_num_copies(fs_info, stripe->bg->start,
stripe->bg->length); stripe->bg->length);
int mirror; int mirror;
...@@ -1069,7 +1075,23 @@ static void scrub_stripe_read_repair_worker(struct work_struct *work) ...@@ -1069,7 +1075,23 @@ static void scrub_stripe_read_repair_worker(struct work_struct *work)
goto out; goto out;
} }
out: out:
scrub_stripe_report_errors(stripe->sctx, stripe); /*
* Submit the repaired sectors. For zoned case, we cannot do repair
* in-place, but queue the bg to be relocated.
*/
if (btrfs_is_zoned(fs_info)) {
if (!bitmap_empty(&stripe->error_bitmap, stripe->nr_sectors))
btrfs_repair_one_zone(fs_info, sctx->stripes[0].bg->start);
} else if (!sctx->readonly) {
unsigned long repaired;
bitmap_andnot(&repaired, &stripe->init_error_bitmap,
&stripe->error_bitmap, stripe->nr_sectors);
scrub_write_sectors(sctx, stripe, repaired, false);
wait_scrub_stripe_io(stripe);
}
scrub_stripe_report_errors(sctx, stripe);
set_bit(SCRUB_STRIPE_FLAG_REPAIR_DONE, &stripe->state); set_bit(SCRUB_STRIPE_FLAG_REPAIR_DONE, &stripe->state);
wake_up(&stripe->repair_wait); wake_up(&stripe->repair_wait);
} }
...@@ -1720,32 +1742,6 @@ static int flush_scrub_stripes(struct scrub_ctx *sctx) ...@@ -1720,32 +1742,6 @@ static int flush_scrub_stripes(struct scrub_ctx *sctx)
test_bit(SCRUB_STRIPE_FLAG_REPAIR_DONE, &stripe->state)); test_bit(SCRUB_STRIPE_FLAG_REPAIR_DONE, &stripe->state));
} }
/*
* Submit the repaired sectors. For zoned case, we cannot do repair
* in-place, but queue the bg to be relocated.
*/
if (btrfs_is_zoned(fs_info)) {
for (int i = 0; i < nr_stripes; i++) {
stripe = &sctx->stripes[i];
if (!bitmap_empty(&stripe->error_bitmap, stripe->nr_sectors)) {
btrfs_repair_one_zone(fs_info,
sctx->stripes[0].bg->start);
break;
}
}
} else if (!sctx->readonly) {
for (int i = 0; i < nr_stripes; i++) {
unsigned long repaired;
stripe = &sctx->stripes[i];
bitmap_andnot(&repaired, &stripe->init_error_bitmap,
&stripe->error_bitmap, stripe->nr_sectors);
scrub_write_sectors(sctx, stripe, repaired, false);
}
}
/* Submit for dev-replace. */ /* Submit for dev-replace. */
if (sctx->is_dev_replace) { if (sctx->is_dev_replace) {
/* /*
...@@ -1918,24 +1914,6 @@ static int scrub_raid56_parity_stripe(struct scrub_ctx *sctx, ...@@ -1918,24 +1914,6 @@ static int scrub_raid56_parity_stripe(struct scrub_ctx *sctx,
/* For now, no zoned support for RAID56. */ /* For now, no zoned support for RAID56. */
ASSERT(!btrfs_is_zoned(sctx->fs_info)); ASSERT(!btrfs_is_zoned(sctx->fs_info));
/* Writeback for the repaired sectors. */
for (int i = 0; i < data_stripes; i++) {
unsigned long repaired;
stripe = &sctx->raid56_data_stripes[i];
bitmap_andnot(&repaired, &stripe->init_error_bitmap,
&stripe->error_bitmap, stripe->nr_sectors);
scrub_write_sectors(sctx, stripe, repaired, false);
}
/* Wait for the above writebacks to finish. */
for (int i = 0; i < data_stripes; i++) {
stripe = &sctx->raid56_data_stripes[i];
wait_scrub_stripe_io(stripe);
}
/* /*
* Now all data stripes are properly verified. Check if we have any * Now all data stripes are properly verified. Check if we have any
* unrepaired, if so abort immediately or we could further corrupt the * unrepaired, if so abort immediately or we could further corrupt the
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment