From: Konstantinos Skarlatos <k.skarlatos@gmail.com>
To: Wang Shilong <wangsl.fnst@cn.fujitsu.com>, linux-btrfs@vger.kernel.org
Subject: Re: [PATCH] Btrfs-progs: fsck: add an option to check data csums
Date: Thu, 08 May 2014 13:48:43 +0300 [thread overview]
Message-ID: <536B610B.9070909@gmail.com> (raw)
In-Reply-To: <1399512409-661-1-git-send-email-wangsl.fnst@cn.fujitsu.com>
On 8/5/2014 4:26 πμ, Wang Shilong wrote:
> This patch adds an option '--check-data-csum' to verify data csums.
> fsck won't check data csums unless users specify this option explictly.
Can this option be added to btrfs restore as well? i think it would be a
good thing if users can tell restore to only recover non-corrupt files.
>
> 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;
>
next prev parent reply other threads:[~2014-05-08 10:48 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
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 [this message]
2014-05-16 15:49 ` David Sterba
2014-05-16 15:40 ` David Sterba
2014-05-28 1:34 ` Wang Shilong
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=536B610B.9070909@gmail.com \
--to=k.skarlatos@gmail.com \
--cc=linux-btrfs@vger.kernel.org \
--cc=wangsl.fnst@cn.fujitsu.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.