@@ -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. */
}
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(-)