Commit ace9e12d authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
parents 858fd168 79b8ee70
Loading
Loading
Loading
Loading
+5 −4
Original line number Diff line number Diff line
@@ -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
Original line number Diff line number Diff line
@@ -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 @@ static void scrub_stripe_report_errors(struct scrub_ctx *sctx,
	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;

+6 −0
Original line number Diff line number Diff line
@@ -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:
	/*