summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWang Shilong <wangsl.fnst@cn.fujitsu.com>2014-03-06 13:53:59 +0800
committerChris Mason <clm@fb.com>2014-03-21 06:23:38 -0700
commit706a90b1223594b95898e3e0355b42354b238669 (patch)
treebb5c1917a26731cc4a770698f38f968b3d88dc84
parent5ec1876c2c7b9495723053e9b4c85adf24821331 (diff)
Btrfs-progs: fsck: force to udate tree root for some cases
commit roots won't update root item in tree root if it finds updated root's bytenr is same as before. However, this is not right for fsck, we need update tree root in the following case: 1.overwrite previous root node. 2.reinit reloc data tree, this is because we skip pin relo data tree before which means we can allocate same block as before. Fix this by updating tree root ourselves for the above cases. Signed-off-by: Wang Shilong <wangsl.fnst@cn.fujitsu.com> Signed-off-by: David Sterba <dsterba@suse.cz> Signed-off-by: Chris Mason <clm@fb.com>
-rw-r--r--cmds-check.c23
1 files changed, 22 insertions, 1 deletions
diff --git a/cmds-check.c b/cmds-check.c
index 4b2a8f01..ae611d1d 100644
--- a/cmds-check.c
+++ b/cmds-check.c
@@ -5906,6 +5906,7 @@ static int btrfs_fsck_reinit_root(struct btrfs_trans_handle *trans,
struct extent_buffer *c;
struct extent_buffer *old = root->node;
int level;
+ int ret;
struct btrfs_disk_key disk_key = {0,0,0};
level = 0;
@@ -5922,6 +5923,7 @@ static int btrfs_fsck_reinit_root(struct btrfs_trans_handle *trans,
if (IS_ERR(c)) {
c = old;
extent_buffer_get(c);
+ overwrite = 1;
}
init:
memset_extent_buffer(c, 0, 0, sizeof(struct btrfs_header));
@@ -5939,7 +5941,26 @@ init:
BTRFS_UUID_SIZE);
btrfs_mark_buffer_dirty(c);
-
+ /*
+ * this case can happen in the following case:
+ *
+ * 1.overwrite previous root.
+ *
+ * 2.reinit reloc data root, this is because we skip pin
+ * down reloc data tree before which means we can allocate
+ * same block bytenr here.
+ */
+ if (old->start == c->start) {
+ btrfs_set_root_generation(&root->root_item,
+ trans->transid);
+ root->root_item.level = btrfs_header_level(root->node);
+ ret = btrfs_update_root(trans, root->fs_info->tree_root,
+ &root->root_key, &root->root_item);
+ if (ret) {
+ free_extent_buffer(c);
+ return ret;
+ }
+ }
free_extent_buffer(old);
root->node = c;
add_root_to_dirty_list(root);