180 lines
4.7 KiB
Diff
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
|
||
|
|