linux-btrfs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
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


  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).