Commit 7192833c authored by Naohiro Aota's avatar Naohiro Aota Committed by David Sterba
Browse files

btrfs: scrub: run relocation repair when/only needed



When btrfs scrub finds an error, it reads mirrors to find correct data. If
all the errors are fixed, sctx->error_bitmap is cleared for the stripe
range. However, in the zoned mode, it runs relocation to repair scrub
errors when the bitmap is *not* empty, which is a flipped condition.

Also, it runs the relocation even if the scrub is read-only. This was
missed by a fix in commit 1f2030ff ("btrfs: scrub: respect the
read-only flag during repair").

The repair is only necessary when there is a repaired sector and should be
done on read-write scrub. So, tweak the condition for both regular and
zoned case.

Fixes: 54765392 ("btrfs: scrub: introduce helper to queue a stripe for scrub")
Fixes: 1f2030ff ("btrfs: scrub: respect the read-only flag during repair")
CC: stable@vger.kernel.org # 6.6+
Reviewed-by: default avatarQu Wenruo <wqu@suse.com>
Reviewed-by: default avatarJohannes Thumshirn <johannes.thumshirn@wdc.com>
Signed-off-by: default avatarNaohiro Aota <naohiro.aota@wdc.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent e5a78fde
Loading
Loading
Loading
Loading
+9 −9
Original line number Diff line number Diff line
@@ -1012,6 +1012,7 @@ static void scrub_stripe_read_repair_worker(struct work_struct *work)
	struct btrfs_fs_info *fs_info = sctx->fs_info;
	int num_copies = btrfs_num_copies(fs_info, stripe->bg->start,
					  stripe->bg->length);
	unsigned long repaired;
	int mirror;
	int i;

@@ -1078,17 +1079,16 @@ static void scrub_stripe_read_repair_worker(struct work_struct *work)
	 * Submit the repaired sectors.  For zoned case, we cannot do repair
	 * in-place, but queue the bg to be relocated.
	 */
	bitmap_andnot(&repaired, &stripe->init_error_bitmap, &stripe->error_bitmap,
		      stripe->nr_sectors);
	if (!sctx->readonly && !bitmap_empty(&repaired, stripe->nr_sectors)) {
		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);
		} else {
			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);