Btrfs: add the tree history log to btrfs-progs
authorChris Mason <chris.mason@oracle.com>
Sat, 5 Nov 2011 18:58:41 +0000 (14:58 -0400)
committerChris Mason <chris.mason@oracle.com>
Sat, 5 Nov 2011 18:58:41 +0000 (14:58 -0400)
This also adds btrfs-debug-tree -R to print the history

Signed-off-by: Chris Mason <chris.mason@oracle.com>
ctree.h
debug-tree.c

diff --git a/ctree.h b/ctree.h
index b1a87c8..54748c8 100644 (file)
--- 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);
index 91e0064..2aeabfd 100644 (file)
@@ -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",