linux-btrfs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] Btrfs-progs: fsck: add an option to check data csums
@ 2014-05-08  1:26 Wang Shilong
  2014-05-08 10:48 ` Konstantinos Skarlatos
  2014-05-16 15:40 ` David Sterba
  0 siblings, 2 replies; 5+ messages in thread
From: Wang Shilong @ 2014-05-08  1:26 UTC (permalink / raw)
  To: linux-btrfs

This patch adds an option '--check-data-csum' to verify data csums.
fsck won't check data csums unless users specify this option explictly.

Signed-off-by: Wang Shilong <wangsl.fnst@cn.fujitsu.com>
---
 Documentation/btrfs-check.txt |   2 +
 cmds-check.c                  | 122 ++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 120 insertions(+), 4 deletions(-)

diff --git a/Documentation/btrfs-check.txt b/Documentation/btrfs-check.txt
index 485a49c..bc10755 100644
--- a/Documentation/btrfs-check.txt
+++ b/Documentation/btrfs-check.txt
@@ -30,6 +30,8 @@ try to repair the filesystem.
 create a new CRC tree.
 --init-extent-tree::
 create a new extent tree.
+--check-data-csum::
+check data csums.
 
 EXIT STATUS
 -----------
diff --git a/cmds-check.c b/cmds-check.c
index 103efc5..b53d49c 100644
--- a/cmds-check.c
+++ b/cmds-check.c
@@ -53,6 +53,7 @@ static LIST_HEAD(delete_items);
 static int repair = 0;
 static int no_holes = 0;
 static int init_extent_tree = 0;
+static int check_data_csum = 0;
 
 struct extent_backref {
 	struct list_head list;
@@ -3634,6 +3635,106 @@ static int check_space_cache(struct btrfs_root *root)
 	return error ? -EINVAL : 0;
 }
 
+static int read_extent_data(struct btrfs_root *root, char *data,
+			u64 logical, u64 len, int mirror)
+{
+	u64 offset = 0;
+	struct btrfs_multi_bio *multi = NULL;
+	struct btrfs_fs_info *info = root->fs_info;
+	struct btrfs_device *device;
+	int ret = 0;
+	u64 read_len;
+	unsigned long bytes_left = len;
+
+	while (bytes_left) {
+		read_len = bytes_left;
+		device = NULL;
+		ret = btrfs_map_block(&info->mapping_tree, READ,
+				logical + offset, &read_len, &multi,
+				mirror, NULL);
+		if (ret) {
+			fprintf(stderr, "Couldn't map the block %llu\n",
+					logical + offset);
+			goto error;
+		}
+		device = multi->stripes[0].dev;
+
+		if (device->fd == 0)
+			goto error;
+
+		if (read_len > root->sectorsize)
+			read_len = root->sectorsize;
+		if (read_len > bytes_left)
+			read_len = bytes_left;
+
+		ret = pread64(device->fd, data + offset, read_len,
+			      multi->stripes[0].physical);
+		if (ret != read_len)
+			goto error;
+		offset += read_len;
+		bytes_left -= read_len;
+		kfree(multi);
+		multi = NULL;
+	}
+	return 0;
+error:
+	kfree(multi);
+	return -EIO;
+}
+
+static int check_extent_csums(struct btrfs_root *root, u64 bytenr,
+			u64 num_bytes, unsigned long leaf_offset,
+			struct extent_buffer *eb) {
+
+	u64 offset = 0;
+	u16 csum_size = btrfs_super_csum_size(root->fs_info->super_copy);
+	char *data;
+	u32 crc;
+	unsigned long tmp;
+	char result[csum_size];
+	char out[csum_size];
+	int ret = 0;
+	__s64 cmp;
+	int mirror;
+	int num_copies = btrfs_num_copies(&root->fs_info->mapping_tree,
+				bytenr, num_bytes);
+
+	BUG_ON(num_bytes % root->sectorsize);
+	data = malloc(root->sectorsize);
+	if (!data)
+		return -ENOMEM;
+
+	while (offset < num_bytes) {
+		mirror = 0;
+again:
+		ret = read_extent_data(root, data, bytenr + offset,
+				root->sectorsize, mirror);
+		if (ret)
+			goto out;
+
+		crc = ~(u32)0;
+		crc = btrfs_csum_data(NULL, (char *)data, crc,
+				      root->sectorsize);
+		btrfs_csum_final(crc, result);
+
+		tmp = leaf_offset + offset / root->sectorsize * csum_size;
+		read_extent_buffer(eb, out, tmp, csum_size);
+		cmp = memcmp(out, result, csum_size);
+		if (cmp) {
+			fprintf(stderr, "mirror: %d range bytenr: %llu, len: %d checksum mismatch\n",
+				mirror, bytenr + offset, root->sectorsize);
+			if (mirror < num_copies - 1) {
+				mirror += 1;
+				goto again;
+			}
+		}
+		offset += root->sectorsize;
+	}
+out:
+	free(data);
+	return ret;
+}
+
 static int check_extent_exists(struct btrfs_root *root, u64 bytenr,
 			       u64 num_bytes)
 {
@@ -3771,6 +3872,8 @@ static int check_csums(struct btrfs_root *root)
 	u16 csum_size = btrfs_super_csum_size(root->fs_info->super_copy);
 	int errors = 0;
 	int ret;
+	u64 data_len;
+	unsigned long leaf_offset;
 
 	root = root->fs_info->csum_root;
 
@@ -3812,6 +3915,16 @@ static int check_csums(struct btrfs_root *root)
 			continue;
 		}
 
+		data_len = (btrfs_item_size_nr(leaf, path->slots[0]) /
+			      csum_size) * root->sectorsize;
+		if (!check_data_csum)
+			goto skip_csum_check;
+		leaf_offset = btrfs_item_ptr_offset(leaf, path->slots[0]);
+		ret = check_extent_csums(root, key.offset, data_len,
+					 leaf_offset, leaf);
+		if (ret)
+			break;
+skip_csum_check:
 		if (!num_bytes) {
 			offset = key.offset;
 		} else if (key.offset != offset + num_bytes) {
@@ -3825,9 +3938,7 @@ static int check_csums(struct btrfs_root *root)
 			offset = key.offset;
 			num_bytes = 0;
 		}
-
-		num_bytes += (btrfs_item_size_nr(leaf, path->slots[0]) /
-			      csum_size) * root->sectorsize;
+		num_bytes += data_len;
 		path->slots[0]++;
 	}
 
@@ -6665,6 +6776,7 @@ static struct option long_options[] = {
 	{ "repair", 0, NULL, 0 },
 	{ "init-csum-tree", 0, NULL, 0 },
 	{ "init-extent-tree", 0, NULL, 0 },
+	{ "check-data-csum", 0, NULL, 0 },
 	{ "backup", 0, NULL, 0 },
 	{ NULL, 0, NULL, 0}
 };
@@ -6678,6 +6790,7 @@ const char * const cmd_check_usage[] = {
 	"--repair                    try to repair the filesystem",
 	"--init-csum-tree            create a new CRC tree",
 	"--init-extent-tree          create a new extent tree",
+	"--check-data-csum           check data csums",
 	NULL
 };
 
@@ -6736,8 +6849,9 @@ int cmd_check(int argc, char **argv)
 			ctree_flags |= (OPEN_CTREE_WRITES |
 					OPEN_CTREE_NO_BLOCK_GROUPS);
 			repair = 1;
+		} else if (option_index == 4) {
+			check_data_csum = 1;
 		}
-
 	}
 	argc = argc - optind;
 
-- 
1.9.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2014-05-28  1:38 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-05-08  1:26 [PATCH] Btrfs-progs: fsck: add an option to check data csums Wang Shilong
2014-05-08 10:48 ` Konstantinos Skarlatos
2014-05-16 15:49   ` David Sterba
2014-05-16 15:40 ` David Sterba
2014-05-28  1:34   ` Wang Shilong

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).