From: Qu Wenruo <wqu@suse.com>
To: linux-btrfs@vger.kernel.org
Subject: [PATCH v2 2/5] btrfs-progs: check: move csum tree population into mode-common.[ch]
Date: Fri, 14 Jan 2022 08:51:20 +0800 [thread overview]
Message-ID: <20220114005123.19426-3-wqu@suse.com> (raw)
In-Reply-To: <20220114005123.19426-1-wqu@suse.com>
This part has no mode specific operations, just move them into
mode-common.[ch].
Signed-off-by: Qu Wenruo <wqu@suse.com>
---
check/main.c | 244 --------------------------------------------
check/mode-common.c | 244 ++++++++++++++++++++++++++++++++++++++++++++
check/mode-common.h | 1 +
3 files changed, 245 insertions(+), 244 deletions(-)
diff --git a/check/main.c b/check/main.c
index 540130b8e223..ea2f2d7b16b8 100644
--- a/check/main.c
+++ b/check/main.c
@@ -9557,250 +9557,6 @@ static int zero_log_tree(struct btrfs_root *root)
return ret;
}
-static int populate_csum(struct btrfs_trans_handle *trans,
- struct btrfs_root *csum_root, char *buf, u64 start,
- u64 len)
-{
- u64 offset = 0;
- u64 sectorsize;
- int ret = 0;
-
- while (offset < len) {
- sectorsize = gfs_info->sectorsize;
- ret = read_extent_data(gfs_info, buf, start + offset,
- §orsize, 0);
- if (ret)
- break;
- ret = btrfs_csum_file_block(trans, start + len, start + offset,
- buf, sectorsize);
- if (ret)
- break;
- offset += sectorsize;
- }
- return ret;
-}
-
-static int fill_csum_tree_from_one_fs_root(struct btrfs_trans_handle *trans,
- struct btrfs_root *cur_root)
-{
- struct btrfs_root *csum_root;
- struct btrfs_path path;
- struct btrfs_key key;
- struct extent_buffer *node;
- struct btrfs_file_extent_item *fi;
- char *buf = NULL;
- u64 start = 0;
- u64 len = 0;
- int slot = 0;
- int ret = 0;
-
- buf = malloc(gfs_info->sectorsize);
- if (!buf)
- return -ENOMEM;
-
- btrfs_init_path(&path);
- key.objectid = 0;
- key.offset = 0;
- key.type = 0;
- ret = btrfs_search_slot(NULL, cur_root, &key, &path, 0, 0);
- if (ret < 0)
- goto out;
- /* Iterate all regular file extents and fill its csum */
- while (1) {
- btrfs_item_key_to_cpu(path.nodes[0], &key, path.slots[0]);
-
- if (key.type != BTRFS_EXTENT_DATA_KEY)
- goto next;
- node = path.nodes[0];
- slot = path.slots[0];
- fi = btrfs_item_ptr(node, slot, struct btrfs_file_extent_item);
- if (btrfs_file_extent_type(node, fi) != BTRFS_FILE_EXTENT_REG)
- goto next;
- start = btrfs_file_extent_disk_bytenr(node, fi);
- len = btrfs_file_extent_disk_num_bytes(node, fi);
-
- csum_root = btrfs_csum_root(gfs_info, start);
- ret = populate_csum(trans, csum_root, buf, start, len);
- if (ret == -EEXIST)
- ret = 0;
- if (ret < 0)
- goto out;
-next:
- /*
- * TODO: if next leaf is corrupted, jump to nearest next valid
- * leaf.
- */
- ret = btrfs_next_item(cur_root, &path);
- if (ret < 0)
- goto out;
- if (ret > 0) {
- ret = 0;
- goto out;
- }
- }
-
-out:
- btrfs_release_path(&path);
- free(buf);
- return ret;
-}
-
-static int fill_csum_tree_from_fs(struct btrfs_trans_handle *trans)
-{
- struct btrfs_path path;
- struct btrfs_root *tree_root = gfs_info->tree_root;
- struct btrfs_root *cur_root;
- struct extent_buffer *node;
- struct btrfs_key key;
- int slot = 0;
- int ret = 0;
-
- btrfs_init_path(&path);
- key.objectid = BTRFS_FS_TREE_OBJECTID;
- key.offset = 0;
- key.type = BTRFS_ROOT_ITEM_KEY;
- ret = btrfs_search_slot(NULL, tree_root, &key, &path, 0, 0);
- if (ret < 0)
- goto out;
- if (ret > 0) {
- ret = -ENOENT;
- goto out;
- }
-
- while (1) {
- node = path.nodes[0];
- slot = path.slots[0];
- btrfs_item_key_to_cpu(node, &key, slot);
- if (key.objectid > BTRFS_LAST_FREE_OBJECTID)
- goto out;
- if (key.type != BTRFS_ROOT_ITEM_KEY)
- goto next;
- if (!is_fstree(key.objectid))
- goto next;
- key.offset = (u64)-1;
-
- cur_root = btrfs_read_fs_root(gfs_info, &key);
- if (IS_ERR(cur_root) || !cur_root) {
- fprintf(stderr, "Fail to read fs/subvol tree: %lld\n",
- key.objectid);
- goto out;
- }
- ret = fill_csum_tree_from_one_fs_root(trans, cur_root);
- if (ret < 0)
- goto out;
-next:
- ret = btrfs_next_item(tree_root, &path);
- if (ret > 0) {
- ret = 0;
- goto out;
- }
- if (ret < 0)
- goto out;
- }
-
-out:
- btrfs_release_path(&path);
- return ret;
-}
-
-static int fill_csum_tree_from_extent(struct btrfs_trans_handle *trans,
- struct btrfs_root *extent_root)
-{
- struct btrfs_root *csum_root;
- struct btrfs_path path;
- struct btrfs_extent_item *ei;
- struct extent_buffer *leaf;
- char *buf;
- struct btrfs_key key;
- int ret;
-
- btrfs_init_path(&path);
- key.objectid = 0;
- key.type = BTRFS_EXTENT_ITEM_KEY;
- key.offset = 0;
- ret = btrfs_search_slot(NULL, extent_root, &key, &path, 0, 0);
- if (ret < 0) {
- btrfs_release_path(&path);
- return ret;
- }
-
- buf = malloc(gfs_info->sectorsize);
- if (!buf) {
- btrfs_release_path(&path);
- return -ENOMEM;
- }
-
- while (1) {
- if (path.slots[0] >= btrfs_header_nritems(path.nodes[0])) {
- ret = btrfs_next_leaf(extent_root, &path);
- if (ret < 0)
- break;
- if (ret) {
- ret = 0;
- break;
- }
- }
- leaf = path.nodes[0];
-
- btrfs_item_key_to_cpu(leaf, &key, path.slots[0]);
- if (key.type != BTRFS_EXTENT_ITEM_KEY) {
- path.slots[0]++;
- continue;
- }
-
- ei = btrfs_item_ptr(leaf, path.slots[0],
- struct btrfs_extent_item);
- if (!(btrfs_extent_flags(leaf, ei) &
- BTRFS_EXTENT_FLAG_DATA)) {
- path.slots[0]++;
- continue;
- }
-
- csum_root = btrfs_csum_root(gfs_info, key.objectid);
- ret = populate_csum(trans, csum_root, buf, key.objectid,
- key.offset);
- if (ret)
- break;
- path.slots[0]++;
- }
-
- btrfs_release_path(&path);
- free(buf);
- return ret;
-}
-
-/*
- * Recalculate the csum and put it into the csum tree.
- *
- * Extent tree init will wipe out all the extent info, so in that case, we
- * can't depend on extent tree, but use fs tree. If search_fs_tree is set, we
- * will use fs/subvol trees to init the csum tree.
- */
-static int fill_csum_tree(struct btrfs_trans_handle *trans,
- int search_fs_tree)
-{
- struct btrfs_root *root;
- struct rb_node *n;
- int ret;
-
- if (search_fs_tree)
- return fill_csum_tree_from_fs(trans);
-
- root = btrfs_extent_root(gfs_info, 0);
- while (1) {
- ret = fill_csum_tree_from_extent(trans, root);
- if (ret)
- break;
- n = rb_next(&root->rb_node);
- if (!n)
- break;
- root = rb_entry(n, struct btrfs_root, rb_node);
- if (root->root_key.objectid != BTRFS_EXTENT_TREE_OBJECTID)
- break;
- }
- return ret;
-}
-
static void free_roots_info_cache(void)
{
if (!roots_info_cache)
diff --git a/check/mode-common.c b/check/mode-common.c
index 62a9837bde5e..1608dbdafa4c 100644
--- a/check/mode-common.c
+++ b/check/mode-common.c
@@ -1191,3 +1191,247 @@ error:
btrfs_abort_transaction(trans, ret);
return ret;
}
+
+static int populate_csum(struct btrfs_trans_handle *trans,
+ struct btrfs_root *csum_root, char *buf, u64 start,
+ u64 len)
+{
+ u64 offset = 0;
+ u64 sectorsize;
+ int ret = 0;
+
+ while (offset < len) {
+ sectorsize = gfs_info->sectorsize;
+ ret = read_extent_data(gfs_info, buf, start + offset,
+ §orsize, 0);
+ if (ret)
+ break;
+ ret = btrfs_csum_file_block(trans, start + len, start + offset,
+ buf, sectorsize);
+ if (ret)
+ break;
+ offset += sectorsize;
+ }
+ return ret;
+}
+
+static int fill_csum_tree_from_one_fs_root(struct btrfs_trans_handle *trans,
+ struct btrfs_root *cur_root)
+{
+ struct btrfs_root *csum_root;
+ struct btrfs_path path;
+ struct btrfs_key key;
+ struct extent_buffer *node;
+ struct btrfs_file_extent_item *fi;
+ char *buf = NULL;
+ u64 start = 0;
+ u64 len = 0;
+ int slot = 0;
+ int ret = 0;
+
+ buf = malloc(gfs_info->sectorsize);
+ if (!buf)
+ return -ENOMEM;
+
+ btrfs_init_path(&path);
+ key.objectid = 0;
+ key.offset = 0;
+ key.type = 0;
+ ret = btrfs_search_slot(NULL, cur_root, &key, &path, 0, 0);
+ if (ret < 0)
+ goto out;
+ /* Iterate all regular file extents and fill its csum */
+ while (1) {
+ btrfs_item_key_to_cpu(path.nodes[0], &key, path.slots[0]);
+
+ if (key.type != BTRFS_EXTENT_DATA_KEY)
+ goto next;
+ node = path.nodes[0];
+ slot = path.slots[0];
+ fi = btrfs_item_ptr(node, slot, struct btrfs_file_extent_item);
+ if (btrfs_file_extent_type(node, fi) != BTRFS_FILE_EXTENT_REG)
+ goto next;
+ start = btrfs_file_extent_disk_bytenr(node, fi);
+ len = btrfs_file_extent_disk_num_bytes(node, fi);
+
+ csum_root = btrfs_csum_root(gfs_info, start);
+ ret = populate_csum(trans, csum_root, buf, start, len);
+ if (ret == -EEXIST)
+ ret = 0;
+ if (ret < 0)
+ goto out;
+next:
+ /*
+ * TODO: if next leaf is corrupted, jump to nearest next valid
+ * leaf.
+ */
+ ret = btrfs_next_item(cur_root, &path);
+ if (ret < 0)
+ goto out;
+ if (ret > 0) {
+ ret = 0;
+ goto out;
+ }
+ }
+
+out:
+ btrfs_release_path(&path);
+ free(buf);
+ return ret;
+}
+
+static int fill_csum_tree_from_fs(struct btrfs_trans_handle *trans)
+{
+ struct btrfs_path path;
+ struct btrfs_root *tree_root = gfs_info->tree_root;
+ struct btrfs_root *cur_root;
+ struct extent_buffer *node;
+ struct btrfs_key key;
+ int slot = 0;
+ int ret = 0;
+
+ btrfs_init_path(&path);
+ key.objectid = BTRFS_FS_TREE_OBJECTID;
+ key.offset = 0;
+ key.type = BTRFS_ROOT_ITEM_KEY;
+ ret = btrfs_search_slot(NULL, tree_root, &key, &path, 0, 0);
+ if (ret < 0)
+ goto out;
+ if (ret > 0) {
+ ret = -ENOENT;
+ goto out;
+ }
+
+ while (1) {
+ node = path.nodes[0];
+ slot = path.slots[0];
+ btrfs_item_key_to_cpu(node, &key, slot);
+ if (key.objectid > BTRFS_LAST_FREE_OBJECTID)
+ goto out;
+ if (key.type != BTRFS_ROOT_ITEM_KEY)
+ goto next;
+ if (!is_fstree(key.objectid))
+ goto next;
+ key.offset = (u64)-1;
+
+ cur_root = btrfs_read_fs_root(gfs_info, &key);
+ if (IS_ERR(cur_root) || !cur_root) {
+ fprintf(stderr, "Fail to read fs/subvol tree: %lld\n",
+ key.objectid);
+ goto out;
+ }
+ ret = fill_csum_tree_from_one_fs_root(trans, cur_root);
+ if (ret < 0)
+ goto out;
+next:
+ ret = btrfs_next_item(tree_root, &path);
+ if (ret > 0) {
+ ret = 0;
+ goto out;
+ }
+ if (ret < 0)
+ goto out;
+ }
+
+out:
+ btrfs_release_path(&path);
+ return ret;
+}
+
+static int fill_csum_tree_from_extent(struct btrfs_trans_handle *trans,
+ struct btrfs_root *extent_root)
+{
+ struct btrfs_root *csum_root;
+ struct btrfs_path path;
+ struct btrfs_extent_item *ei;
+ struct extent_buffer *leaf;
+ char *buf;
+ struct btrfs_key key;
+ int ret;
+
+ btrfs_init_path(&path);
+ key.objectid = 0;
+ key.type = BTRFS_EXTENT_ITEM_KEY;
+ key.offset = 0;
+ ret = btrfs_search_slot(NULL, extent_root, &key, &path, 0, 0);
+ if (ret < 0) {
+ btrfs_release_path(&path);
+ return ret;
+ }
+
+ buf = malloc(gfs_info->sectorsize);
+ if (!buf) {
+ btrfs_release_path(&path);
+ return -ENOMEM;
+ }
+
+ while (1) {
+ if (path.slots[0] >= btrfs_header_nritems(path.nodes[0])) {
+ ret = btrfs_next_leaf(extent_root, &path);
+ if (ret < 0)
+ break;
+ if (ret) {
+ ret = 0;
+ break;
+ }
+ }
+ leaf = path.nodes[0];
+
+ btrfs_item_key_to_cpu(leaf, &key, path.slots[0]);
+ if (key.type != BTRFS_EXTENT_ITEM_KEY) {
+ path.slots[0]++;
+ continue;
+ }
+
+ ei = btrfs_item_ptr(leaf, path.slots[0],
+ struct btrfs_extent_item);
+ if (!(btrfs_extent_flags(leaf, ei) &
+ BTRFS_EXTENT_FLAG_DATA)) {
+ path.slots[0]++;
+ continue;
+ }
+
+ csum_root = btrfs_csum_root(gfs_info, key.objectid);
+ ret = populate_csum(trans, csum_root, buf, key.objectid,
+ key.offset);
+ if (ret)
+ break;
+ path.slots[0]++;
+ }
+
+ btrfs_release_path(&path);
+ free(buf);
+ return ret;
+}
+
+/*
+ * Recalculate the csum and put it into the csum tree.
+ *
+ * @search_fs_tree: How to get the data extent item.
+ * If true, iterate all fs roots to get all
+ * extent data (which can be slow).
+ * Otherwise, search extent tree for extent data.
+ */
+int fill_csum_tree(struct btrfs_trans_handle *trans, bool search_fs_tree)
+{
+ struct btrfs_root *root;
+ struct rb_node *n;
+ int ret;
+
+ if (search_fs_tree)
+ return fill_csum_tree_from_fs(trans);
+
+ root = btrfs_extent_root(gfs_info, 0);
+ while (1) {
+ ret = fill_csum_tree_from_extent(trans, root);
+ if (ret)
+ break;
+ n = rb_next(&root->rb_node);
+ if (!n)
+ break;
+ root = rb_entry(n, struct btrfs_root, rb_node);
+ if (root->root_key.objectid != BTRFS_EXTENT_TREE_OBJECTID)
+ break;
+ }
+ return ret;
+}
diff --git a/check/mode-common.h b/check/mode-common.h
index 8cd135b9bfc2..b894c2be4f97 100644
--- a/check/mode-common.h
+++ b/check/mode-common.h
@@ -199,4 +199,5 @@ static inline void btrfs_check_subpage_eb_alignment(struct btrfs_fs_info *info,
int repair_dev_item_bytes_used(struct btrfs_fs_info *fs_info,
u64 devid, u64 bytes_used_expected);
+int fill_csum_tree(struct btrfs_trans_handle *trans, bool search_fs_tree);
#endif
--
2.34.1
next prev parent reply other threads:[~2022-01-14 0:51 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-01-14 0:51 [PATCH v2 0/5] btrfs-progs: check: properly generate csum for various complex combinations Qu Wenruo
2022-01-14 0:51 ` [PATCH v2 1/5] btrfs-progs: backref: properly queue indirect refs Qu Wenruo
2022-01-14 0:51 ` Qu Wenruo [this message]
2022-01-14 0:51 ` [PATCH v2 3/5] btrfs-progs: check: don't calculate csum for preallocated file extents Qu Wenruo
2022-01-14 0:51 ` [PATCH v2 4/5] btrfs-progs: check: handle csum generation properly for `--init-csum-tree --init-extent-tree` Qu Wenruo
2022-01-14 0:51 ` [PATCH v2 5/5] btrfs-progs: fsck-tests: add test case for init-csum-tree Qu Wenruo
2022-01-14 16:40 ` David Sterba
2022-01-14 23:40 ` Qu Wenruo
2022-01-17 13:50 ` David Sterba
2022-01-14 16:50 ` [PATCH v2 0/5] btrfs-progs: check: properly generate csum for various complex combinations David Sterba
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=20220114005123.19426-3-wqu@suse.com \
--to=wqu@suse.com \
--cc=linux-btrfs@vger.kernel.org \
/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 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).