From: Qu Wenruo <quwenruo@cn.fujitsu.com>
To: <linux-btrfs@vger.kernel.org>
Subject: [PATCH 6/7] btrfs-progs: Introduce new function reset_(one_root/roots)_csum() to reset one/all tree's csum in tree root.
Date: Wed, 4 Feb 2015 15:16:52 +0800 [thread overview]
Message-ID: <1423034213-14018-9-git-send-email-quwenruo@cn.fujitsu.com> (raw)
In-Reply-To: <1423034213-14018-1-git-send-email-quwenruo@cn.fujitsu.com>
New function reset_one_root_csum() will reset all csum in one root.
And reset_roots_csum() will reset all csum of all trees in tree root.
which provides the basis for later dangerous options.
Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com>
---
cmds-check.c | 176 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 176 insertions(+)
diff --git a/cmds-check.c b/cmds-check.c
index e4b4f4a..535a518 100644
--- a/cmds-check.c
+++ b/cmds-check.c
@@ -9193,6 +9193,182 @@ out:
return ret;
}
+static int reset_one_root_csum(struct btrfs_root *root)
+{
+ struct btrfs_fs_info *fs_info = root->fs_info;
+ struct btrfs_path *path;
+ struct btrfs_key key;
+ struct extent_buffer *node;
+ u32 sectorsize = root->sectorsize;
+ int max_level = btrfs_root_level(&root->root_item);
+ int slot;
+ int i;
+ int ret = 0;
+
+ path = btrfs_alloc_path();
+ if (!path)
+ return -ENOMEM;
+ path->reada = 0;
+
+ /* Iterate all levels except level 0 */
+ for (i = 0; i < max_level; i++) {
+ int cur_level = max_level - i;
+
+ path->lowest_level = cur_level;
+ key.offset = 0;
+ key.objectid = 0;
+ key.type = 0;
+
+ /*
+ * btrfs_search_slot() can't work with lowest_level and cow,
+ * so use inslen=0 and cow=0 and later modify will be done
+ * directly to disk.
+ */
+ ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
+ if (ret < 0)
+ goto out;
+
+ /* Iterate all node slots in this level */
+ while (1) {
+ u64 bytenr;
+
+ node = path->nodes[0];
+ slot = path->slots[0];
+ bytenr = btrfs_node_blockptr(node, slot);
+
+ if (bytenr != round_down(bytenr, sectorsize)) {
+ bytenr = round_down(bytenr, sectorsize);
+ btrfs_set_node_blockptr(node, slot, bytenr);
+ ret = write_tree_block(NULL, root, node);
+ if (ret < 0) {
+ fprintf(stderr,
+ "Fail to write extent at %llu\n",
+ bytenr);
+ goto out;
+ }
+ }
+ ret = reset_tree_block_csum(fs_info, bytenr,
+ root->nodesize);
+ if (ret < 0) {
+ fprintf(stderr,
+ "Fail to reset csum for tree block at %llu\n",
+ bytenr);
+ goto out;
+ }
+
+ ret = btrfs_next_slot(root, path, cur_level);
+ /*
+ * Error should not happen since higher level iteration
+ * has already reset the csum of this level.
+ * Either way, goto next level should be OK.
+ */
+ if (ret)
+ break;
+ }
+ btrfs_release_path(path);
+ }
+out:
+ btrfs_free_path(path);
+ return ret;
+}
+
+static int reset_roots_csum(struct btrfs_root *tree_root)
+{
+ struct btrfs_fs_info *fs_info = tree_root->fs_info;
+ struct btrfs_key key;
+ struct btrfs_path *path;
+ struct btrfs_root_item *ri;
+ struct btrfs_root *root;
+ struct extent_buffer *node;
+ u32 nodesize = tree_root->nodesize;
+ u32 sectorsize = tree_root->sectorsize;
+ u64 bytenr;
+ int slot;
+ int ret = 0;
+
+ path = btrfs_alloc_path();
+ if (!path)
+ return -ENOMEM;
+
+ key.objectid = 0;
+ key.offset = 0;
+ key.type = 0;
+
+ /*
+ * Tree root is OK and we can do cow. But in case extent tree is
+ * corrupted, we still use the nocow method.
+ */
+ ret = btrfs_search_slot(NULL, tree_root, &key, path, 0, 0);
+ if (ret < 0)
+ goto out;
+ while (1) {
+ slot = path->slots[0];
+ node = path->nodes[0];
+ btrfs_item_key_to_cpu(node, &key, slot);
+ if (key.type != BTRFS_ROOT_ITEM_KEY)
+ goto next;
+
+ /*
+ * skip tree reloc tree, it's not support by
+ * btrfs_read_fs_root() yet.
+ */
+ if (key.objectid == BTRFS_TREE_RELOC_OBJECTID)
+ goto next;
+
+ ri = btrfs_item_ptr(node, slot, struct btrfs_root_item);
+ bytenr = btrfs_disk_root_bytenr(node, ri);
+
+ /*
+ * Check if the bytenr is aligned.
+ * If the error bit is only in the low all zero bits,
+ * no real damage will happen since we will align it.
+ */
+ if (round_down(bytenr, sectorsize) != bytenr) {
+ bytenr = round_down(bytenr, sectorsize);
+ btrfs_set_disk_root_bytenr(node, ri, bytenr);
+ ret = write_tree_block(NULL, root, node);
+ if (ret < 0) {
+ fprintf(stderr,
+ "Fail to write extent at %llu\n",
+ bytenr);
+ goto out;
+ }
+ }
+
+ ret = reset_tree_block_csum(fs_info, bytenr, nodesize);
+ if (ret < 0) {
+ fprintf(stderr,
+ "Failed to reset root for tree %llu, skip it\n",
+ key.objectid);
+ goto next;
+ }
+ key.offset = (u64)-1;
+ root = btrfs_read_fs_root(fs_info, &key);
+ if (!root || IS_ERR(root) ||
+ !extent_buffer_uptodate(root->node)) {
+ fprintf(stderr,
+ "Root of tree %lld is still corrupted, skip it\n",
+ key.objectid);
+ goto next;
+ }
+ ret = reset_one_root_csum(root);
+ if (ret < 0)
+ goto next;
+
+next:
+ ret = btrfs_next_item(tree_root, path);
+ if (ret < 0)
+ goto out;
+ if (ret > 0) {
+ ret = 0;
+ goto out;
+ }
+ }
+out:
+ btrfs_free_path(path);
+ return ret;
+}
+
const char * const cmd_check_usage[] = {
"btrfs check [options] <device>",
"Check an unmounted btrfs filesystem.",
--
2.2.2
next prev parent reply other threads:[~2015-02-04 7:20 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-02-04 7:16 [PATCH 0/7] Allow btrfsck to reset csum of all tree blocks, AKA dangerous mode Qu Wenruo
2015-02-04 7:16 ` [PATCH 1/7] btrfs-progs: Add btrfs_(prev/next)_tree_block() to keep search result in the same level of path->lowest_level Qu Wenruo
2015-02-04 7:16 ` [PATCH 2/7] btrfs-progs: Introduce btrfs_next_slot() function to iterate to next slot in given level Qu Wenruo
2015-02-04 7:16 ` [PATCH 3/7] btrfs-progs: Allow btrfs_read_fs_root() to re-read the tree node Qu Wenruo
2015-02-04 7:16 ` [PATCH 4/7] btrfs-progs: Export write_tree_block() and allow it to do nocow write Qu Wenruo
2015-02-04 7:16 ` [PATCH 4/5] btrfs-progs: Introduce new function reset_tree_block_csum() for later tree block csum reset Qu Wenruo
2015-02-04 7:16 ` [PATCH 5/5] btrfs-progs: Introduce new function reset_(one_root/roots)_csum() to reset one/all tree's csum in tree root Qu Wenruo
2015-02-04 7:16 ` [PATCH 5/7] btrfs-progs: Introduce new function reset_tree_block_csum() for later tree block csum reset Qu Wenruo
2015-02-04 7:16 ` Qu Wenruo [this message]
2015-02-04 7:16 ` [PATCH 7/7] btrfs-progs: Introduce "--dangerous" option to reset all tree block csum Qu Wenruo
2015-02-04 9:16 ` [PATCH 0/7] Allow btrfsck to reset csum of all tree blocks, AKA dangerous mode Martin Steigerwald
2015-02-04 10:07 ` Paul Jones
2015-02-05 1:43 ` Qu Wenruo
2015-02-05 1:35 ` Qu Wenruo
2015-02-05 8:31 ` Martin Steigerwald
2015-02-05 8:45 ` Qu Wenruo
2015-02-05 8:59 ` BTRFS wiki: page about recovery (was: Re: [PATCH 0/7] Allow btrfsck to reset csum of all tree blocks, AKA dangerous mode.) Martin Steigerwald
2015-04-22 5:55 ` [PATCH 0/7] Allow btrfsck to reset csum of all tree blocks, AKA dangerous mode Qu Wenruo
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=1423034213-14018-9-git-send-email-quwenruo@cn.fujitsu.com \
--to=quwenruo@cn.fujitsu.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).