btrfsprogs/0163-btrfsck-add-init-csum-tree-to-replace-the-csum-root-.patch
David Sterba 2c5c7c6753 - add btrfsck repair options for:
- rebuild extent records
  - fix block group accounting
  - reset csums for rescue nodatasum mount
  - prune corrupt extent allocation tree blocks
- device scanning fixes for dm and multipath
- initrd support: move btrfs device scan after block device setup
- documentation updates
- add csize for file commpressed size
- updated restore utility

OBS-URL: https://build.opensuse.org/package/show/filesystems/btrfsprogs?expand=0&rev=118
2012-03-05 15:09:24 +00:00

180 lines
4.7 KiB
Diff

From 80a0a84e46d07d2b2b07991ee2813b017301786c Mon Sep 17 00:00:00 2001
From: Chris Mason <chris.mason@oracle.com>
Date: Thu, 9 Feb 2012 10:38:05 -0500
Subject: [PATCH 12/18] btrfsck: add --init-csum-tree to replace the csum root
with an empty one
This will effectively delete all of your crcs, but at least you'll
be able to mount the FS with nodatasum.
Signed-off-by: Chris Mason <chris.mason@oracle.com>
---
btrfsck.c | 27 ++++++++++++++++++++++-----
ctree.c | 40 ++++++++++++++++++++++++++++++++++++++++
ctree.h | 2 ++
disk-io.c | 3 ++-
4 files changed, 66 insertions(+), 6 deletions(-)
diff --git a/btrfsck.c b/btrfsck.c
index 1320238..a451397 100644
--- a/btrfsck.c
+++ b/btrfsck.c
@@ -3171,6 +3171,7 @@ static void print_usage(void)
static struct option long_options[] = {
{ "super", 1, NULL, 's' },
{ "repair", 0, NULL, 0 },
+ { "init-csum-tree", 0, NULL, 0 },
{ 0, 0, 0, 0}
};
@@ -3185,6 +3186,8 @@ int main(int ac, char **av)
int num;
int repair = 0;
int option_index = 0;
+ int init_csum_tree = 0;
+ int rw = 0;
while(1) {
int c;
@@ -3206,6 +3209,11 @@ int main(int ac, char **av)
if (option_index == 1) {
printf("enabling repair mode\n");
repair = 1;
+ rw = 1;
+ } else if (option_index == 2) {
+ printf("Creating a new CRC tree\n");
+ init_csum_tree = 1;
+ rw = 1;
}
}
@@ -3225,7 +3233,7 @@ int main(int ac, char **av)
return -EBUSY;
}
- info = open_ctree_fs_info(av[optind], bytenr, repair, 1);
+ info = open_ctree_fs_info(av[optind], bytenr, rw, 1);
if (info == NULL)
return 1;
@@ -3241,9 +3249,19 @@ int main(int ac, char **av)
root = info->fs_root;
fprintf(stderr, "checking extents\n");
- if (repair)
+ if (rw)
trans = btrfs_start_transaction(root, 1);
+ if (init_csum_tree) {
+ fprintf(stderr, "Reinit crc root\n");
+ ret = btrfs_fsck_reinit_root(trans, info->csum_root);
+ if (ret) {
+ fprintf(stderr, "crc root initialization failed\n");
+ return -EIO;
+ }
+ goto out;
+ }
+
ret = check_extents(trans, root, repair);
if (ret)
goto out;
@@ -3260,15 +3278,14 @@ int main(int ac, char **av)
ret = check_root_refs(root, &root_cache);
out:
free_root_recs(&root_cache);
- if (repair) {
+ if (rw) {
ret = btrfs_commit_transaction(trans, root);
if (ret)
exit(1);
}
close_ctree(root);
- if (found_old_backref) {
- /*
+ if (found_old_backref) { /*
* there was a disk format change when mixed
* backref was in testing tree. The old format
* existed about one week.
diff --git a/ctree.c b/ctree.c
index 005550f..282c868 100644
--- a/ctree.c
+++ b/ctree.c
@@ -138,6 +138,46 @@ int btrfs_copy_root(struct btrfs_trans_handle *trans,
return 0;
}
+int btrfs_fsck_reinit_root(struct btrfs_trans_handle *trans,
+ struct btrfs_root *root)
+{
+ struct extent_buffer *c;
+ struct extent_buffer *old = root->node;
+ int level;
+ struct btrfs_disk_key disk_key = {0,0,0};
+
+ level = 0;
+
+ c = btrfs_alloc_free_block(trans, root,
+ btrfs_level_size(root, 0),
+ root->root_key.objectid,
+ &disk_key, level, 0, 0);
+ if (IS_ERR(c))
+ return PTR_ERR(c);
+
+ memset_extent_buffer(c, 0, 0, sizeof(struct btrfs_header));
+ btrfs_set_header_level(c, level);
+ btrfs_set_header_bytenr(c, c->start);
+ btrfs_set_header_generation(c, trans->transid);
+ btrfs_set_header_backref_rev(c, BTRFS_MIXED_BACKREF_REV);
+ btrfs_set_header_owner(c, root->root_key.objectid);
+
+ write_extent_buffer(c, root->fs_info->fsid,
+ (unsigned long)btrfs_header_fsid(c),
+ BTRFS_FSID_SIZE);
+
+ write_extent_buffer(c, root->fs_info->chunk_tree_uuid,
+ (unsigned long)btrfs_header_chunk_tree_uuid(c),
+ BTRFS_UUID_SIZE);
+
+ btrfs_mark_buffer_dirty(c);
+
+ free_extent_buffer(old);
+ root->node = c;
+ add_root_to_dirty_list(root);
+ return 0;
+}
+
/*
* check if the tree block can be shared by multiple trees
*/
diff --git a/ctree.h b/ctree.h
index 6f12869..c53f65a 100644
--- a/ctree.h
+++ b/ctree.h
@@ -1851,6 +1851,8 @@ int btrfs_update_block_group(struct btrfs_trans_handle *trans,
struct btrfs_root *root, u64 bytenr, u64 num,
int alloc, int mark_free);
/* ctree.c */
+int btrfs_fsck_reinit_root(struct btrfs_trans_handle *trans,
+ struct btrfs_root *root);
void reada_for_search(struct btrfs_root *root, struct btrfs_path *path,
int level, int slot, u64 objectid);
struct extent_buffer *read_node_slot(struct btrfs_root *root,
diff --git a/disk-io.c b/disk-io.c
index e9fdba8..d9df313 100644
--- a/disk-io.c
+++ b/disk-io.c
@@ -793,7 +793,8 @@ static struct btrfs_fs_info *__open_ctree_fd(int fp, const char *path, u64 sb_by
BTRFS_CSUM_TREE_OBJECTID, csum_root);
if (ret) {
printk("Couldn't setup csum tree\n");
- goto out_failed;
+ if (!partial)
+ goto out_failed;
}
csum_root->track_dirty = 1;
--
1.7.6.233.gd79bc