diff mbox series

[PoC,8/9] btrfs: scrub: implement data verification code for scrub_fs

Message ID c83d3feb9812f0c3047b39ef97db3c9d9ca3ab35.1662191784.git.wqu@suse.com (mailing list archive)
State New, archived
Headers show
Series btrfs: scrub: introduce a new family of ioctl, scrub_fs | expand

Commit Message

Qu Wenruo Sept. 3, 2022, 8:19 a.m. UTC
For data verification it's much simpler, only need to do csum
verification and we have very handy helper for it.

Signed-off-by: Qu Wenruo <wqu@suse.com>
---
 fs/btrfs/scrub.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 57 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c
index f587d0373517..145bd5c9601d 100644
--- a/fs/btrfs/scrub.c
+++ b/fs/btrfs/scrub.c
@@ -5226,6 +5226,60 @@  static void scrub_fs_verify_meta(struct scrub_fs_ctx *sfctx, int sector_nr)
 		scrub_fs_verify_one_meta(sfctx, sector_nr, i);
 }
 
+/* Convert a sector pointer to its index inside sfctx->sectors[] array. */
+static int scrub_fs_sector_to_sector_index(struct scrub_fs_ctx *sfctx,
+					   struct scrub_fs_sector *sector)
+{
+	int i;
+
+	ASSERT(sector);
+	for (i = 0; i < sfctx->total_sectors; i++) {
+		if (&sfctx->sectors[i] == sector)
+			break;
+	}
+	/* As long as @sector is from sfctx->sectors[], we should have found it. */
+	ASSERT(i < sfctx->total_sectors);
+	return i; 
+}
+
+static void scrub_fs_verify_one_data(struct scrub_fs_ctx *sfctx, int sector_nr,
+				     int mirror_nr)
+{
+	struct btrfs_fs_info *fs_info = sfctx->fs_info;
+	struct scrub_fs_sector *sector =
+		scrub_fs_get_sector(sfctx, sector_nr, mirror_nr);
+	int index = scrub_fs_sector_to_sector_index(sfctx, sector);
+	struct page *data_page = scrub_fs_get_page(sfctx, index);
+	unsigned int data_page_off = scrub_fs_get_page_offset(sfctx, index);
+	u8 csum_result[BTRFS_CSUM_SIZE];
+	u8 *csum_expected = sector->csum;
+	int ret;
+
+	sfctx->stat.data_scrubbed += fs_info->sectorsize;
+
+	/* No IO done, just increase the accounting. */
+	if (!(sector->flags & SCRUB_FS_SECTOR_FLAG_IO_DONE)) {
+		sfctx->stat.data_io_fail += fs_info->sectorsize;
+		return;
+	}
+
+	/*
+	 * NODATASUM case, just skip, we will come back later to determine
+	 * the status when checking the sectors inside the same vertical stripe.
+	 */
+	if (!csum_expected)
+		return;
+
+	ret = btrfs_check_sector_csum(fs_info, data_page, data_page_off,
+				      csum_result, csum_expected);
+	if (ret < 0) {
+		sfctx->stat.data_csum_mismatch += fs_info->sectorsize;
+		return;
+	}
+	/* All good. */
+	sector->flags |= SCRUB_FS_SECTOR_FLAG_GOOD;
+}
+
 static void scrub_fs_verify_one_stripe(struct scrub_fs_ctx *sfctx)
 {
 	struct btrfs_fs_info *fs_info = sfctx->fs_info;
@@ -5236,6 +5290,7 @@  static void scrub_fs_verify_one_stripe(struct scrub_fs_ctx *sfctx)
 	for (sector_nr = 0; sector_nr < sectors_per_stripe; sector_nr++) {
 		struct scrub_fs_sector *sector =
 			scrub_fs_get_sector(sfctx, sector_nr, 0);
+		int mirror_nr;
 
 		/*
 		 * All sectors in the same veritical stripe should share
@@ -5258,7 +5313,8 @@  static void scrub_fs_verify_one_stripe(struct scrub_fs_ctx *sfctx)
 			continue;
 		}
 
-		/* Place holder for data verification. */
+		for (mirror_nr = 0; mirror_nr < sfctx->nr_copies; mirror_nr++)
+			scrub_fs_verify_one_data(sfctx, sector_nr, mirror_nr);
 	}
 	/* Place holder for recoverable checks. */
 }