@@ -5117,6 +5117,41 @@ static void scrub_fs_verify_meta(struct scrub_fs_endio_ctrl *endio_ctrl,
}
}
+static void scrub_fs_verify_data(struct scrub_fs_endio_ctrl *endio_ctrl,
+ int sector_nr, int mirror_nr)
+{
+ struct scrub_fs_ctx *sfctx = endio_ctrl->sfctx;
+ struct btrfs_fs_info *fs_info = sfctx->fs_info;
+ struct scrub_fs_sector *sector =
+ scrub_fs_get_sector(sfctx, sector_nr, mirror_nr);
+ u8 csum_result[BTRFS_CSUM_SIZE] = {0};
+ u8 *csum_expected = sector->csum;
+ unsigned int set_flag;
+ int ret;
+
+ scrub_fs_check_sector_mirror_nr(sfctx, sector_nr, mirror_nr);
+
+ /*
+ * No checksum case, we can not determine if it's preallocate or real
+ * NODATASUM. Just mark it good unconditionally.
+ */
+ if (!csum_expected) {
+ set_flag = SCRUB_FS_SECTOR_FLAG_GOOD;
+ goto out;
+ }
+
+ ret = btrfs_check_sector_csum(fs_info,
+ scrub_fs_get_page(sfctx, sector_nr, mirror_nr),
+ scrub_fs_get_page_offset(sfctx, sector_nr, mirror_nr),
+ csum_result, csum_expected);
+ if (ret < 0)
+ set_flag = SCRUB_FS_SECTOR_FLAG_BAD_CSUM;
+ else
+ set_flag = SCRUB_FS_SECTOR_FLAG_GOOD;
+out:
+ sector->flags |= set_flag;
+}
+
static void scrub_fs_read_endio(struct bio *bio)
{
struct scrub_fs_endio_ctrl *endio_ctrl = bio->bi_private;
@@ -5163,9 +5198,10 @@ static void scrub_fs_read_endio(struct bio *bio)
!(sector->flags & SCRUB_FS_SECTOR_FLAG_IO_DONE))
continue;
- /* Place holder for data verification. */
- if (sector->flags & SCRUB_FS_SECTOR_FLAG_DATA)
+ if (sector->flags & SCRUB_FS_SECTOR_FLAG_DATA) {
+ scrub_fs_verify_data(endio_ctrl, i, mirror_nr);
continue;
+ }
/* We must be at a metadata sector. */
ASSERT(sector->flags & SCRUB_FS_SECTOR_FLAG_META);
For data verification it's much simpler, only need to do csum verification and we already have very handy helper for it. Signed-off-by: Qu Wenruo <wqu@suse.com> --- fs/btrfs/scrub.c | 40 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-)