Merge tag 'for-6.4-rc6-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux
Pull btrfs fixes from David Sterba:
"A more fixes and regression fixes:
- in subpage mode, fix crash when repairing metadata at the end of
a stripe
- properly enable async discard when remounting from read-only to
read-write
- scrub regression fixes:
- respect read-only scrub when attempting to do a repair
- fix reporting of found errors, the stats don't get properly
accounted after a stripe repair"
* tag 'for-6.4-rc6-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux:
btrfs: scrub: also report errors hit during the initial read
btrfs: scrub: respect the read-only flag during repair
btrfs: properly enable async discard when switching from RO->RW
btrfs: subpage: fix a crash in metadata repair path
This commit is contained in:
+5
-4
@@ -242,7 +242,6 @@ static int btrfs_repair_eb_io_failure(const struct extent_buffer *eb,
|
||||
int mirror_num)
|
||||
{
|
||||
struct btrfs_fs_info *fs_info = eb->fs_info;
|
||||
u64 start = eb->start;
|
||||
int i, num_pages = num_extent_pages(eb);
|
||||
int ret = 0;
|
||||
|
||||
@@ -251,12 +250,14 @@ static int btrfs_repair_eb_io_failure(const struct extent_buffer *eb,
|
||||
|
||||
for (i = 0; i < num_pages; i++) {
|
||||
struct page *p = eb->pages[i];
|
||||
u64 start = max_t(u64, eb->start, page_offset(p));
|
||||
u64 end = min_t(u64, eb->start + eb->len, page_offset(p) + PAGE_SIZE);
|
||||
u32 len = end - start;
|
||||
|
||||
ret = btrfs_repair_io_failure(fs_info, 0, start, PAGE_SIZE,
|
||||
start, p, start - page_offset(p), mirror_num);
|
||||
ret = btrfs_repair_io_failure(fs_info, 0, start, len,
|
||||
start, p, offset_in_page(start), mirror_num);
|
||||
if (ret)
|
||||
break;
|
||||
start += PAGE_SIZE;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
+19
-7
@@ -134,8 +134,14 @@ struct scrub_stripe {
|
||||
* The errors hit during the initial read of the stripe.
|
||||
*
|
||||
* Would be utilized for error reporting and repair.
|
||||
*
|
||||
* The remaining init_nr_* records the number of errors hit, only used
|
||||
* by error reporting.
|
||||
*/
|
||||
unsigned long init_error_bitmap;
|
||||
unsigned int init_nr_io_errors;
|
||||
unsigned int init_nr_csum_errors;
|
||||
unsigned int init_nr_meta_errors;
|
||||
|
||||
/*
|
||||
* The following error bitmaps are all for the current status.
|
||||
@@ -1003,12 +1009,9 @@ skip:
|
||||
sctx->stat.data_bytes_scrubbed += nr_data_sectors << fs_info->sectorsize_bits;
|
||||
sctx->stat.tree_bytes_scrubbed += nr_meta_sectors << fs_info->sectorsize_bits;
|
||||
sctx->stat.no_csum += nr_nodatacsum_sectors;
|
||||
sctx->stat.read_errors +=
|
||||
bitmap_weight(&stripe->io_error_bitmap, stripe->nr_sectors);
|
||||
sctx->stat.csum_errors +=
|
||||
bitmap_weight(&stripe->csum_error_bitmap, stripe->nr_sectors);
|
||||
sctx->stat.verify_errors +=
|
||||
bitmap_weight(&stripe->meta_error_bitmap, stripe->nr_sectors);
|
||||
sctx->stat.read_errors += stripe->init_nr_io_errors;
|
||||
sctx->stat.csum_errors += stripe->init_nr_csum_errors;
|
||||
sctx->stat.verify_errors += stripe->init_nr_meta_errors;
|
||||
sctx->stat.uncorrectable_errors +=
|
||||
bitmap_weight(&stripe->error_bitmap, stripe->nr_sectors);
|
||||
sctx->stat.corrected_errors += nr_repaired_sectors;
|
||||
@@ -1041,6 +1044,12 @@ static void scrub_stripe_read_repair_worker(struct work_struct *work)
|
||||
scrub_verify_one_stripe(stripe, stripe->extent_sector_bitmap);
|
||||
/* Save the initial failed bitmap for later repair and report usage. */
|
||||
stripe->init_error_bitmap = stripe->error_bitmap;
|
||||
stripe->init_nr_io_errors = bitmap_weight(&stripe->io_error_bitmap,
|
||||
stripe->nr_sectors);
|
||||
stripe->init_nr_csum_errors = bitmap_weight(&stripe->csum_error_bitmap,
|
||||
stripe->nr_sectors);
|
||||
stripe->init_nr_meta_errors = bitmap_weight(&stripe->meta_error_bitmap,
|
||||
stripe->nr_sectors);
|
||||
|
||||
if (bitmap_empty(&stripe->init_error_bitmap, stripe->nr_sectors))
|
||||
goto out;
|
||||
@@ -1490,6 +1499,9 @@ static void scrub_stripe_reset_bitmaps(struct scrub_stripe *stripe)
|
||||
{
|
||||
stripe->extent_sector_bitmap = 0;
|
||||
stripe->init_error_bitmap = 0;
|
||||
stripe->init_nr_io_errors = 0;
|
||||
stripe->init_nr_csum_errors = 0;
|
||||
stripe->init_nr_meta_errors = 0;
|
||||
stripe->error_bitmap = 0;
|
||||
stripe->io_error_bitmap = 0;
|
||||
stripe->csum_error_bitmap = 0;
|
||||
@@ -1730,7 +1742,7 @@ static int flush_scrub_stripes(struct scrub_ctx *sctx)
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
} else if (!sctx->readonly) {
|
||||
for (int i = 0; i < nr_stripes; i++) {
|
||||
unsigned long repaired;
|
||||
|
||||
|
||||
@@ -1841,6 +1841,12 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data)
|
||||
btrfs_clear_sb_rdonly(sb);
|
||||
|
||||
set_bit(BTRFS_FS_OPEN, &fs_info->flags);
|
||||
|
||||
/*
|
||||
* If we've gone from readonly -> read/write, we need to get
|
||||
* our sync/async discard lists in the right state.
|
||||
*/
|
||||
btrfs_discard_resume(fs_info);
|
||||
}
|
||||
out:
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user