Introduce a new function, scrub_data_mirror(), to check mirror based
data blocks.

Signed-off-by: Qu Wenruo <quwen...@cn.fujitsu.com>
---
 check/scrub.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 67 insertions(+)

diff --git a/check/scrub.c b/check/scrub.c
index ce8d5e5..5cd8bc4 100644
--- a/check/scrub.c
+++ b/check/scrub.c
@@ -157,3 +157,70 @@ out:
        return ret;
 }
 
+static int scrub_data_mirror(struct btrfs_fs_info *fs_info,
+                            struct btrfs_scrub_progress *scrub_ctx,
+                            char *data, u64 start, u64 len, int mirror)
+{
+       u64 cur = 0;
+       u32 csum;
+       u32 sectorsize = fs_info->tree_root->sectorsize;
+       char *buf = NULL;
+       int ret = 0;
+       int err = 0;
+
+       if (!data) {
+               buf = malloc(len);
+               if (!buf)
+                       return -ENOMEM;
+               /* Read out as much data as possible to speed up read */
+               while (cur < len) {
+                       u64 read_len = len - cur;
+
+                       ret = read_extent_data(fs_info->tree_root, buf + cur,
+                                       start + cur, &read_len, mirror);
+                       if (ret < 0) {
+                               error("failed to read out data at logical 
bytenr %llu mirror %d",
+                                     start + cur, mirror);
+                               scrub_ctx->read_errors++;
+                               goto out;
+                       }
+                       scrub_ctx->data_bytes_scrubbed += read_len;
+                       cur += read_len;
+               }
+       } else {
+               buf = data;
+       }
+
+       /* Check csum per-sectorsize */
+       cur = 0;
+       while (cur < len) {
+               u32 data_csum = ~(u32)0;
+
+               ret = btrfs_read_one_data_csum(fs_info, start + cur, &csum);
+               if (ret > 0) {
+                       scrub_ctx->csum_discards++;
+                       /* In case some csum are missing */
+                       goto next;
+               }
+               data_csum = btrfs_csum_data(NULL, buf + cur, data_csum,
+                                           sectorsize);
+               btrfs_csum_final(data_csum, (u8 *)&data_csum);
+               if (data_csum != csum) {
+                       error("data at bytenr %llu mirror %d csum mismatch, 
have %u expect %u",
+                             start + cur, mirror, data_csum, csum);
+                       err = 1;
+                       scrub_ctx->csum_errors++;
+                       cur += sectorsize;
+                       continue;
+               }
+               scrub_ctx->data_bytes_scrubbed += sectorsize;
+next:
+               cur += sectorsize;
+       }
+out:
+       if (!data)
+               free(buf);
+       if (!ret && err)
+               return -EIO;
+       return ret;
+}
-- 
2.10.0



--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to