Commit af31f5e5 authored by Chris Mason's avatar Chris Mason

Btrfs: add a log of past tree roots

This takes some of the free space in the btrfs super block
to record information about most of the roots in the last four
commits.

It also adds a -o recovery to use the root history log when
we're not able to read the tree of tree roots, the extent
tree root, the device tree root or the csum root.
Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
parent 6c41761f
...@@ -360,6 +360,47 @@ struct btrfs_header { ...@@ -360,6 +360,47 @@ struct btrfs_header {
#define BTRFS_SYSTEM_CHUNK_ARRAY_SIZE 2048 #define BTRFS_SYSTEM_CHUNK_ARRAY_SIZE 2048
#define BTRFS_LABEL_SIZE 256 #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 * the super block basically lists the main trees of the FS
* it currently lacks any block count etc etc * it currently lacks any block count etc etc
...@@ -406,6 +447,7 @@ struct btrfs_super_block { ...@@ -406,6 +447,7 @@ struct btrfs_super_block {
/* future expansion */ /* future expansion */
__le64 reserved[31]; __le64 reserved[31];
u8 sys_chunk_array[BTRFS_SYSTEM_CHUNK_ARRAY_SIZE]; u8 sys_chunk_array[BTRFS_SYSTEM_CHUNK_ARRAY_SIZE];
struct btrfs_root_backup super_roots[BTRFS_NUM_BACKUP_ROOTS];
} __attribute__ ((__packed__)); } __attribute__ ((__packed__));
/* /*
...@@ -1113,6 +1155,9 @@ struct btrfs_fs_info { ...@@ -1113,6 +1155,9 @@ struct btrfs_fs_info {
u64 fs_state; u64 fs_state;
struct btrfs_delayed_root *delayed_root; struct btrfs_delayed_root *delayed_root;
/* next backup root to be overwritten */
int backup_root_index;
}; };
/* /*
...@@ -1357,6 +1402,7 @@ struct btrfs_ioctl_defrag_range_args { ...@@ -1357,6 +1402,7 @@ struct btrfs_ioctl_defrag_range_args {
#define BTRFS_MOUNT_ENOSPC_DEBUG (1 << 15) #define BTRFS_MOUNT_ENOSPC_DEBUG (1 << 15)
#define BTRFS_MOUNT_AUTO_DEFRAG (1 << 16) #define BTRFS_MOUNT_AUTO_DEFRAG (1 << 16)
#define BTRFS_MOUNT_INODE_MAP_CACHE (1 << 17) #define BTRFS_MOUNT_INODE_MAP_CACHE (1 << 17)
#define BTRFS_MOUNT_RECOVERY (1 << 18)
#define btrfs_clear_opt(o, opt) ((o) &= ~BTRFS_MOUNT_##opt) #define btrfs_clear_opt(o, opt) ((o) &= ~BTRFS_MOUNT_##opt)
#define btrfs_set_opt(o, opt) ((o) |= BTRFS_MOUNT_##opt) #define btrfs_set_opt(o, opt) ((o) |= BTRFS_MOUNT_##opt)
...@@ -1972,6 +2018,55 @@ static inline bool btrfs_root_readonly(struct btrfs_root *root) ...@@ -1972,6 +2018,55 @@ static inline bool btrfs_root_readonly(struct btrfs_root *root)
return root->root_item.flags & BTRFS_ROOT_SUBVOL_RDONLY; return root->root_item.flags & BTRFS_ROOT_SUBVOL_RDONLY;
} }
/* 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 */ /* struct btrfs_super_block */
BTRFS_SETGET_STACK_FUNCS(super_bytenr, struct btrfs_super_block, bytenr, 64); BTRFS_SETGET_STACK_FUNCS(super_bytenr, struct btrfs_super_block, bytenr, 64);
......
This diff is collapsed.
...@@ -164,7 +164,7 @@ enum { ...@@ -164,7 +164,7 @@ enum {
Opt_notreelog, Opt_ratio, Opt_flushoncommit, Opt_discard, Opt_notreelog, Opt_ratio, Opt_flushoncommit, Opt_discard,
Opt_space_cache, Opt_clear_cache, Opt_user_subvol_rm_allowed, Opt_space_cache, Opt_clear_cache, Opt_user_subvol_rm_allowed,
Opt_enospc_debug, Opt_subvolrootid, Opt_defrag, Opt_enospc_debug, Opt_subvolrootid, Opt_defrag,
Opt_inode_cache, Opt_no_space_cache, Opt_err, Opt_inode_cache, Opt_no_space_cache, Opt_recovery, Opt_err,
}; };
static match_table_t tokens = { static match_table_t tokens = {
...@@ -198,6 +198,7 @@ static match_table_t tokens = { ...@@ -198,6 +198,7 @@ static match_table_t tokens = {
{Opt_defrag, "autodefrag"}, {Opt_defrag, "autodefrag"},
{Opt_inode_cache, "inode_cache"}, {Opt_inode_cache, "inode_cache"},
{Opt_no_space_cache, "no_space_cache"}, {Opt_no_space_cache, "no_space_cache"},
{Opt_recovery, "recovery"},
{Opt_err, NULL}, {Opt_err, NULL},
}; };
...@@ -392,6 +393,10 @@ int btrfs_parse_options(struct btrfs_root *root, char *options) ...@@ -392,6 +393,10 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
printk(KERN_INFO "btrfs: enabling auto defrag"); printk(KERN_INFO "btrfs: enabling auto defrag");
btrfs_set_opt(info->mount_opt, AUTO_DEFRAG); btrfs_set_opt(info->mount_opt, AUTO_DEFRAG);
break; break;
case Opt_recovery:
printk(KERN_INFO "btrfs: enabling auto recovery");
btrfs_set_opt(info->mount_opt, RECOVERY);
break;
case Opt_err: case Opt_err:
printk(KERN_INFO "btrfs: unrecognized mount option " printk(KERN_INFO "btrfs: unrecognized mount option "
"'%s'\n", p); "'%s'\n", p);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment