Btrfs-progs: Add chunk tree recover tool
Subsystems (2)
RFC PATCH 1/1 Btrfs-progs: Add chunk tree recover tool
This patch has two parts:
1. In user progs, there need some chunk allocation operations for example mkfs.btrfs which also need to make the first 4096 as stripe header. The way of handle is the same as kernel.
2. the chunk tree recover tool if crash. this tool will first search all the devices for the chunk stripe headers, then it rewrites the sys_chunk_array in super block and rebuilds the chunk tree.
man page:
NAME
btrfs-recover-chunk
DESCRIPTION
-s slient mode, no more information with scan or other -c just scan and check the stripe header to see
whether is good
EXAMPLE
btrfs-recover-chunk /dev/sda9
--- Makefile | 6 +- btrfs-recover-chunk.c | 1403 +++++++++++++++++++++++++++++++++++++++++++++++++ ctree.h | 25 +- disk-io.c | 14 +- disk-io.h | 10 + extent-tree.c | 147 +++++ utils.c | 23 +- utils.h | 1 + volumes.c | 60 ++- volumes.h | 45 ++ 10 files changed, 1705 insertions(+), 29 deletions(-) create mode 100644 btrfs-recover-chunk.c
Makefile +5 -1
@@ -18,7 +18,8 @@ LIBS=-luuid progs = btrfsctl mkfs.btrfs btrfs-debug-tree btrfs-show btrfs-vol btrfsck \ btrfs \ - btrfs-map-logical + btrfs-map-logical \ + btrfs-recover-chunk # make C=1 to enable sparse ifdef C
@@ -37,6 +38,9 @@ all: version $(progs) manpages version: bash version.sh +btrfs-recover-chunk: $(objects) btrfs-recover-chunk.o + gcc $(CFLAGS) -o btrfs-recover-chunk btrfs-recover-chunk.o $(objects) $(LDFLAGS) $(LIBS) + btrfs: $(objects) btrfs.o btrfs_cmds.o gcc $(CFLAGS) -o btrfs btrfs.o btrfs_cmds.o \ $(objects) $(LDFLAGS) $(LIBS)
btrfs-recover-chunk.c new file +1403 -0
1,403 lines not on this page · raw message
ctree.h +22 -3
@@ -349,14 +349,16 @@ struct btrfs_super_block {* Compat flags that we support. If any incompat flags are set other than the * ones specified below then we will fail to mount */ -#define BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF (1ULL << 0) -#define BTRFS_FEATURE_INCOMPAT_DEFAULT_SUBVOL (2ULL << 0) +#define BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF (1ULL << 0) +#define BTRFS_FEATURE_INCOMPAT_DEFAULT_SUBVOL (2ULL << 0) +#define BTRFS_FEATURE_INCOMPAT_CHUNK_TREE_BACKUP (16ULL << 0)#define BTRFS_FEATURE_COMPAT_SUPP 0ULL#define BTRFS_FEATURE_COMPAT_RO_SUPP 0ULL#define BTRFS_FEATURE_INCOMPAT_SUPP \ (BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF | \ - BTRFS_FEATURE_INCOMPAT_DEFAULT_SUBVOL) + BTRFS_FEATURE_INCOMPAT_DEFAULT_SUBVOL | \ + BTRFS_FEATURE_INCOMPAT_CHUNK_TREE_BACKUP)/* * A leaf is full of items. offset and size tell us where to find
@@ -676,6 +678,22 @@ struct btrfs_extent_ops { u64 num_bytes); }; +struct cache_chunk { +u64 offset; +struct btrfs_chunk *chunk; +struct list_head chunk_list; +u8 flag; +}; + +struct recover_control { +int fd; +int silent; +u64 sectorsize; +struct btrfs_fs_devices *fs_devices; +struct list_head sys_chunk_list; +struct list_head non_sys_chunk_list; +}; +struct btrfs_device ;struct btrfs_fs_devices ;struct btrfs_fs_info {
@@ -728,6 +746,7 @@ struct btrfs_fs_info {struct list_head space_info;int system_allocs;int readonly; +struct recover_control *rc; };/*
disk-io.c +10 -4
@@ -258,7 +258,7 @@ int write_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root,return 0 ; } -static int __setup_root (u32 nodesize,u32 leafsize,u32 sectorsize, +int __setup_root (u32 nodesize,u32 leafsize,u32 sectorsize,u32 stripesize,struct btrfs_root *root,struct btrfs_fs_info *fs_info,u64 objectid) {
@@ -394,7 +394,7 @@ commit_tree:return 0 ; } -static int find_and_setup_root (struct btrfs_root *tree_root, +int find_and_setup_root (struct btrfs_root *tree_root,struct btrfs_fs_info *fs_info,u64 objectid,struct btrfs_root *root) {
@@ -417,7 +417,7 @@ static int find_and_setup_root(struct btrfs_root *tree_root,return 0 ; } -static int find_and_setup_log_root (struct btrfs_root *tree_root, +int find_and_setup_log_root (struct btrfs_root *tree_root,struct btrfs_fs_info *fs_info,struct btrfs_super_block *disk_super) {
@@ -456,7 +456,7 @@ int btrfs_free_fs_root(struct btrfs_fs_info *fs_info,return 0 ; } -static int free_fs_roots (struct btrfs_fs_info *fs_info) +int free_fs_roots (struct btrfs_fs_info *fs_info) {struct cache_extent *cache;struct btrfs_root *root;
@@ -629,6 +629,7 @@ struct btrfs_root *open_ctree_fd(int fp, const char *path, u64 sb_bytenr, }memset (fs_info,0 ,sizeof (*fs_info)); + fs_info->rc =NULL ; fs_info->tree_root = tree_root; fs_info->extent_root = extent_root; fs_info->chunk_root = chunk_root;
@@ -688,6 +689,11 @@ struct btrfs_root *open_ctree_fd(int fp, const char *path, u64 sb_bytenr,btrfs_set_super_incompat_flags (disk_super, features); } +if (!(features &BTRFS_FEATURE_INCOMPAT_CHUNK_TREE_BACKUP )) { + features |=BTRFS_FEATURE_INCOMPAT_CHUNK_TREE_BACKUP ; +btrfs_set_super_incompat_flags (disk_super, features); + } + features =btrfs_super_compat_ro_flags (disk_super) & ~BTRFS_FEATURE_COMPAT_RO_SUPP ;if (writes && features) {
disk-io.h +10 -0
@@ -35,6 +35,16 @@ static inline u64 btrfs_sb_offset(int mirror)struct btrfs_device ; +int __setup_root (u32 nodesize,u32 leafsize,u32 sectorsize, +u32 stripesize,struct btrfs_root *root, +struct btrfs_fs_info *fs_info,u64 objectid); +int find_and_setup_root (struct btrfs_root *tree_root, +struct btrfs_fs_info *fs_info, +u64 objectid,struct btrfs_root *root); +int find_and_setup_log_root (struct btrfs_root *tree_root, +struct btrfs_fs_info *fs_info, +struct btrfs_super_block *disk_super); +int free_fs_roots (struct btrfs_fs_info *fs_info);struct extent_buffer *read_tree_block (struct btrfs_root *root,u64 bytenr,u32 blocksize,u64 parent_transid); int readahead_tree_block(struct btrfs_root *root, u64 bytenr, u32 blocksize,
extent-tree.c +147 -0
159 lines not on this page · raw message
utils.c +22 -1
@@ -72,6 +72,7 @@ int make_btrfs(int fd, const char *device, const char *label,struct btrfs_chunk *chunk;struct btrfs_dev_item *dev_item;struct btrfs_dev_extent *dev_extent; +struct btrfs_stripe_header header;u8 chunk_tree_uuid[BTRFS_UUID_SIZE ];u8 *ptr;int i;
@@ -322,6 +323,26 @@ int make_btrfs(int fd, const char *device, const char *label,csum_tree_block_size (buf,BTRFS_CRC32_SIZE ,0 ); ret =pwrite (fd, buf->data, leafsize, blocks[3 ]); +/* mark the the first chunk */ +memset (&header,0 ,sizeof (header)); + header.tag =cpu_to_le64 (BTRFS_STRIPE_HEADER_TAG ); + header.owner =cpu_to_le64 (BTRFS_EXTENT_TREE_OBJECTID ); + header.devid =1 ; + header.dev_offset =0 ; + header.chunk_offset =0 ; + header.chunk_size =cpu_to_le64 (BTRFS_MKFS_SYSTEM_GROUP_SIZE ); + header.type =cpu_to_le64 (BTRFS_BLOCK_GROUP_SYSTEM ); + header.stripe_len =cpu_to_le64 (64 *1024 ); + header.stripe_index =0 ; + header.io_align = sectorsize; + header.io_width = sectorsize; + header.sector_size = sectorsize; + header.num_stripes =1 ; +memcpy (header.uuid, super.dev_item.uuid,BTRFS_UUID_SIZE ); +memcpy (header.fsid, super.fsid,BTRFS_FSID_SIZE ); + header.crc =btrfs_crc32c (0 , (unsigned char *)&header,sizeof (header)); + ret =pwrite (fd, &header,sizeof (header),0 ); +/* create the device tree */ nritems =0 ; itemoff = __BTRFS_LEAF_DATA_SIZE(leafsize) -
@@ -400,7 +421,7 @@ static u64 device_size(int fd, struct stat *st)return 0 ; } -static int zero_blocks (int fd,off_t start,size_t len) +int zero_blocks (int fd,off_t start,size_t len) {char *buf =malloc (len);int ret =0 ;
utils.h +1 -0
@@ -21,6 +21,7 @@#define BTRFS_MKFS_SYSTEM_GROUP_SIZE (4 * 1024 * 1024) +int zero_blocks (int fd,off_t start,size_t len);int make_btrfs (int fd,const char *device,const char *label,u64 blocks[6 ],u64 num_bytes,u32 nodesize,u32 leafsize,u32 sectorsize,u32 stripesize);
volumes.c +40 -20
72 lines not on this page · raw message
volumes.h +45 -0
51 lines not on this page · raw message
-- 1.7.3.1