From 13eced9a0c2b6bd6bc38e6f0f46a1977b1167e67 Mon Sep 17 00:00:00 2001 From: Chris Mason Date: Sat, 5 Nov 2011 14:58:41 -0400 Subject: [PATCH] Btrfs: add the tree history log to btrfs-progs This also adds btrfs-debug-tree -R to print the history Signed-off-by: Chris Mason --- ctree.h | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ debug-tree.c | 49 +++++++++++++++++++++++++++++++- 2 files changed, 139 insertions(+), 1 deletion(-) diff --git a/ctree.h b/ctree.h index b1a87c8..54748c8 100644 --- a/ctree.h +++ b/ctree.h @@ -312,6 +312,47 @@ struct btrfs_header { #define BTRFS_LABEL_SIZE 256 /* + * just in case we somehow lose the roots and are not able to mount, + * we store an array of the roots from previous transactions + * in the super. + */ +#define BTRFS_NUM_BACKUP_ROOTS 4 +struct btrfs_root_backup { + __le64 tree_root; + __le64 tree_root_gen; + + __le64 chunk_root; + __le64 chunk_root_gen; + + __le64 extent_root; + __le64 extent_root_gen; + + __le64 fs_root; + __le64 fs_root_gen; + + __le64 dev_root; + __le64 dev_root_gen; + + __le64 csum_root; + __le64 csum_root_gen; + + __le64 total_bytes; + __le64 bytes_used; + __le64 num_devices; + /* future */ + __le64 unsed_64[4]; + + u8 tree_root_level; + u8 chunk_root_level; + u8 extent_root_level; + u8 fs_root_level; + u8 dev_root_level; + u8 csum_root_level; + /* future and to align */ + u8 unused_8[10]; +} __attribute__ ((__packed__)); + +/* * the super block basically lists the main trees of the FS * it currently lacks any block count etc etc */ @@ -357,6 +398,7 @@ struct btrfs_super_block { /* future expansion */ __le64 reserved[31]; u8 sys_chunk_array[BTRFS_SYSTEM_CHUNK_ARRAY_SIZE]; + struct btrfs_root_backup super_roots[BTRFS_NUM_BACKUP_ROOTS]; } __attribute__ ((__packed__)); /* @@ -1537,6 +1579,55 @@ BTRFS_SETGET_STACK_FUNCS(root_last_snapshot, struct btrfs_root_item, last_snapshot, 64); +/* struct btrfs_root_backup */ +BTRFS_SETGET_STACK_FUNCS(backup_tree_root, struct btrfs_root_backup, + tree_root, 64); +BTRFS_SETGET_STACK_FUNCS(backup_tree_root_gen, struct btrfs_root_backup, + tree_root_gen, 64); +BTRFS_SETGET_STACK_FUNCS(backup_tree_root_level, struct btrfs_root_backup, + tree_root_level, 8); + +BTRFS_SETGET_STACK_FUNCS(backup_chunk_root, struct btrfs_root_backup, + chunk_root, 64); +BTRFS_SETGET_STACK_FUNCS(backup_chunk_root_gen, struct btrfs_root_backup, + chunk_root_gen, 64); +BTRFS_SETGET_STACK_FUNCS(backup_chunk_root_level, struct btrfs_root_backup, + chunk_root_level, 8); + +BTRFS_SETGET_STACK_FUNCS(backup_extent_root, struct btrfs_root_backup, + extent_root, 64); +BTRFS_SETGET_STACK_FUNCS(backup_extent_root_gen, struct btrfs_root_backup, + extent_root_gen, 64); +BTRFS_SETGET_STACK_FUNCS(backup_extent_root_level, struct btrfs_root_backup, + extent_root_level, 8); + +BTRFS_SETGET_STACK_FUNCS(backup_fs_root, struct btrfs_root_backup, + fs_root, 64); +BTRFS_SETGET_STACK_FUNCS(backup_fs_root_gen, struct btrfs_root_backup, + fs_root_gen, 64); +BTRFS_SETGET_STACK_FUNCS(backup_fs_root_level, struct btrfs_root_backup, + fs_root_level, 8); + +BTRFS_SETGET_STACK_FUNCS(backup_dev_root, struct btrfs_root_backup, + dev_root, 64); +BTRFS_SETGET_STACK_FUNCS(backup_dev_root_gen, struct btrfs_root_backup, + dev_root_gen, 64); +BTRFS_SETGET_STACK_FUNCS(backup_dev_root_level, struct btrfs_root_backup, + dev_root_level, 8); + +BTRFS_SETGET_STACK_FUNCS(backup_csum_root, struct btrfs_root_backup, + csum_root, 64); +BTRFS_SETGET_STACK_FUNCS(backup_csum_root_gen, struct btrfs_root_backup, + csum_root_gen, 64); +BTRFS_SETGET_STACK_FUNCS(backup_csum_root_level, struct btrfs_root_backup, + csum_root_level, 8); +BTRFS_SETGET_STACK_FUNCS(backup_total_bytes, struct btrfs_root_backup, + total_bytes, 64); +BTRFS_SETGET_STACK_FUNCS(backup_bytes_used, struct btrfs_root_backup, + bytes_used, 64); +BTRFS_SETGET_STACK_FUNCS(backup_num_devices, struct btrfs_root_backup, + num_devices, 64); + /* struct btrfs_super_block */ BTRFS_SETGET_STACK_FUNCS(super_bytenr, struct btrfs_super_block, bytenr, 64); diff --git a/debug-tree.c b/debug-tree.c index 91e0064..2aeabfd 100644 --- a/debug-tree.c +++ b/debug-tree.c @@ -62,6 +62,45 @@ static void print_extents(struct btrfs_root *root, struct extent_buffer *eb) } } +static void print_old_roots(struct btrfs_super_block *super) +{ + struct btrfs_root_backup *backup; + int i; + + for (i = 0; i < BTRFS_NUM_BACKUP_ROOTS; i++) { + backup = super->super_roots + i; + printf("btrfs root backup slot %d\n", i); + printf("\ttree root gen %llu block %llu\n", + (unsigned long long)btrfs_backup_tree_root_gen(backup), + (unsigned long long)btrfs_backup_tree_root(backup)); + + printf("\t\textent root gen %llu block %llu\n", + (unsigned long long)btrfs_backup_extent_root_gen(backup), + (unsigned long long)btrfs_backup_extent_root(backup)); + + printf("\t\tchunk root gen %llu block %llu\n", + (unsigned long long)btrfs_backup_chunk_root_gen(backup), + (unsigned long long)btrfs_backup_chunk_root(backup)); + + printf("\t\tdevice root gen %llu block %llu\n", + (unsigned long long)btrfs_backup_dev_root_gen(backup), + (unsigned long long)btrfs_backup_dev_root(backup)); + + printf("\t\tcsum root gen %llu block %llu\n", + (unsigned long long)btrfs_backup_csum_root_gen(backup), + (unsigned long long)btrfs_backup_csum_root(backup)); + + printf("\t\tfs root gen %llu block %llu\n", + (unsigned long long)btrfs_backup_fs_root_gen(backup), + (unsigned long long)btrfs_backup_fs_root(backup)); + + printf("\t\t%llu used %llu total %llu devices\n", + (unsigned long long)btrfs_backup_bytes_used(backup), + (unsigned long long)btrfs_backup_total_bytes(backup), + (unsigned long long)btrfs_backup_num_devices(backup)); + } +} + int main(int ac, char **av) { struct btrfs_root *root; @@ -77,6 +116,7 @@ int main(int ac, char **av) int extent_only = 0; int device_only = 0; int roots_only = 0; + int root_backups = 0; u64 block_only = 0; struct btrfs_root *tree_root_scan; @@ -84,7 +124,7 @@ int main(int ac, char **av) while(1) { int c; - c = getopt(ac, av, "deb:r"); + c = getopt(ac, av, "deb:rR"); if (c < 0) break; switch(c) { @@ -97,6 +137,10 @@ int main(int ac, char **av) case 'r': roots_only = 1; break; + case 'R': + roots_only = 1; + root_backups = 1; + break; case 'b': block_only = atoll(optarg); break; @@ -289,6 +333,9 @@ again: if (extent_only || device_only) return 0; + if (root_backups) + print_old_roots(&root->fs_info->super_copy); + printf("total bytes %llu\n", (unsigned long long)btrfs_super_total_bytes(&root->fs_info->super_copy)); printf("bytes used %llu\n", -- 2.7.4