From d23ea8706c91d5a625454de67c9700dfa688d8b5 Mon Sep 17 00:00:00 2001 From: Chris Mason Date: Wed, 11 Apr 2007 13:57:55 -0400 Subject: [PATCH] early support for multiple devices --- Makefile | 2 +- ctree.h | 69 +++++++++++++++++++++++++++++++++++++++++++++---- debug-tree.c | 6 +++++ disk-io.c | 6 +++++ disk-io.h | 2 -- mkfs.c | 72 ++++++++++++++++++++++++++++++++++++++++------------ print-tree.c | 8 ++++++ 7 files changed, 141 insertions(+), 24 deletions(-) diff --git a/Makefile b/Makefile index 219ce80b..7058b088 100644 --- a/Makefile +++ b/Makefile @@ -42,6 +42,6 @@ quick-test: $(objects) quick-test.o $(objects): $(headers) clean : - rm debug-tree tester *.o + rm debug-tree mkfs.btrfs btrfsctl *.o diff --git a/ctree.h b/ctree.h index 8d4ba19d..edd965f3 100644 --- a/ctree.h +++ b/ctree.h @@ -9,10 +9,11 @@ struct btrfs_trans_handle; #define BTRFS_MAGIC "_BtRfS_M" #define BTRFS_ROOT_TREE_OBJECTID 1ULL -#define BTRFS_EXTENT_TREE_OBJECTID 2ULL -#define BTRFS_FS_TREE_OBJECTID 3ULL -#define BTRFS_ROOT_TREE_DIR_OBJECTID 4ULL -#define BTRFS_FIRST_FREE_OBJECTID 5ULL +#define BTRFS_DEV_TREE_OBJECTID 2ULL +#define BTRFS_EXTENT_TREE_OBJECTID 3ULL +#define BTRFS_FS_TREE_OBJECTID 4ULL +#define BTRFS_ROOT_TREE_DIR_OBJECTID 5ULL +#define BTRFS_FIRST_FREE_OBJECTID 6ULL /* * we can actually store much bigger names, but lets not confuse the rest @@ -86,6 +87,10 @@ struct btrfs_super_block { __le64 total_blocks; __le64 blocks_used; __le64 root_dir_objectid; + /* fields below here vary with the underlying disk */ + __le64 device_block_start; + __le64 device_num_blocks; + __le64 device_root; } __attribute__ ((__packed__)); /* @@ -219,10 +224,15 @@ struct btrfs_csum_item { u8 csum[BTRFS_CSUM_SIZE]; } __attribute__ ((__packed__)); +struct btrfs_device_item { + __le16 pathlen; +} __attribute__ ((__packed__)); + struct btrfs_fs_info { struct btrfs_root *fs_root; struct btrfs_root *extent_root; struct btrfs_root *tree_root; + struct btrfs_root *dev_root; struct btrfs_key current_insert; struct btrfs_key last_insert; struct radix_tree_root cache_radix; @@ -300,11 +310,16 @@ struct btrfs_root { */ #define BTRFS_EXTENT_ITEM_KEY 8 +/* + * dev items list the devices that make up the FS + */ +#define BTRFS_DEV_ITEM_KEY 9 + /* * string items are for debugging. They just store a short string of * data in the FS */ -#define BTRFS_STRING_ITEM_KEY 9 +#define BTRFS_STRING_ITEM_KEY 10 static inline u64 btrfs_inode_generation(struct btrfs_inode_item *i) { @@ -770,6 +785,39 @@ static inline void btrfs_set_super_root_dir(struct btrfs_super_block *s, u64 s->root_dir_objectid = cpu_to_le64(val); } +static inline u64 btrfs_super_device_block_start(struct btrfs_super_block *s) +{ + return le64_to_cpu(s->device_block_start); +} + +static inline void btrfs_set_super_device_block_start(struct btrfs_super_block + *s, u64 val) +{ + s->device_block_start = cpu_to_le64(val); +} + +static inline u64 btrfs_super_device_num_blocks(struct btrfs_super_block *s) +{ + return le64_to_cpu(s->device_num_blocks); +} + +static inline void btrfs_set_super_device_num_blocks(struct btrfs_super_block + *s, u64 val) +{ + s->device_num_blocks = cpu_to_le64(val); +} + +static inline u64 btrfs_super_device_root(struct btrfs_super_block *s) +{ + return le64_to_cpu(s->device_root); +} + +static inline void btrfs_set_super_device_root(struct btrfs_super_block + *s, u64 val) +{ + s->device_root = cpu_to_le64(val); +} + static inline u8 *btrfs_leaf_data(struct btrfs_leaf *l) { return (u8 *)l->items; @@ -837,6 +885,17 @@ static inline void btrfs_set_file_extent_num_blocks(struct e->num_blocks = cpu_to_le64(val); } +static inline u16 btrfs_device_pathlen(struct btrfs_device_item *d) +{ + return le16_to_cpu(d->pathlen); +} + +static inline void btrfs_set_device_pathlen(struct btrfs_device_item *d, + u16 val) +{ + d->pathlen = cpu_to_le16(val); +} + /* helper function to cast into the data area of the leaf. */ #define btrfs_item_ptr(leaf, slot, type) \ ((type *)(btrfs_leaf_data(leaf) + \ diff --git a/debug-tree.c b/debug-tree.c index 9699e3c4..229546ae 100644 --- a/debug-tree.c +++ b/debug-tree.c @@ -33,6 +33,9 @@ int main(int ac, char **av) { printf("root tree\n"); btrfs_print_tree(root->fs_info->tree_root, root->fs_info->tree_root->node); + printf("dev tree\n"); + btrfs_print_tree(root->fs_info->dev_root, + root->fs_info->dev_root->node); btrfs_init_path(&path); key.offset = 0; key.objectid = 0; @@ -63,6 +66,9 @@ int main(int ac, char **av) { case BTRFS_ROOT_TREE_OBJECTID: printf("root "); break; + case BTRFS_DEV_TREE_OBJECTID: + printf("dev tree "); + break; case BTRFS_EXTENT_TREE_OBJECTID: printf("extent tree "); break; diff --git a/disk-io.c b/disk-io.c index 448482fb..dff3bd57 100644 --- a/disk-io.c +++ b/disk-io.c @@ -273,6 +273,7 @@ struct btrfs_root *open_ctree_fd(int fp, struct btrfs_super_block *super) struct btrfs_root *root = malloc(sizeof(struct btrfs_root)); struct btrfs_root *extent_root = malloc(sizeof(struct btrfs_root)); struct btrfs_root *tree_root = malloc(sizeof(struct btrfs_root)); + struct btrfs_root *dev_root = malloc(sizeof(struct btrfs_root)); struct btrfs_fs_info *fs_info = malloc(sizeof(*fs_info)); int ret; @@ -286,6 +287,7 @@ struct btrfs_root *open_ctree_fd(int fp, struct btrfs_super_block *super) fs_info->fs_root = root; fs_info->tree_root = tree_root; fs_info->extent_root = extent_root; + fs_info->dev_root = dev_root; fs_info->last_inode_alloc = 0; fs_info->last_inode_alloc_dirid = 0; fs_info->disk_super = super; @@ -299,6 +301,10 @@ struct btrfs_root *open_ctree_fd(int fp, struct btrfs_super_block *super) return NULL; } BUG_ON(ret < 0); + __setup_root(super, dev_root, fs_info, BTRFS_DEV_TREE_OBJECTID, fp); + dev_root->node = read_tree_block(dev_root, + btrfs_super_device_root(super)); + __setup_root(super, tree_root, fs_info, BTRFS_ROOT_TREE_OBJECTID, fp); tree_root->node = read_tree_block(tree_root, btrfs_super_root(super)); BUG_ON(!tree_root->node); diff --git a/disk-io.h b/disk-io.h index d888cf5c..21f353a3 100644 --- a/disk-io.h +++ b/disk-io.h @@ -29,8 +29,6 @@ int close_ctree(struct btrfs_root *root, struct btrfs_super_block *s); void btrfs_block_release(struct btrfs_root *root, struct btrfs_buffer *buf); int write_ctree_super(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_super_block *s); -int mkfs(int fd, u64 num_blocks, u32 blocksize); - #define BTRFS_SUPER_INFO_OFFSET (16 * 1024) #endif diff --git a/mkfs.c b/mkfs.c index 8148259c..58e754b8 100644 --- a/mkfs.c +++ b/mkfs.c @@ -99,7 +99,7 @@ err: return ret; } -int mkfs(int fd, u64 num_blocks, u32 blocksize) +int mkfs(int fd, char *pathname, u64 num_blocks, u32 blocksize) { struct btrfs_super_block super; struct btrfs_leaf *empty_leaf; @@ -107,10 +107,13 @@ int mkfs(int fd, u64 num_blocks, u32 blocksize) struct btrfs_item item; struct btrfs_extent_item extent_item; struct btrfs_inode_item *inode_item; + struct btrfs_device_item dev_item; char *block; int ret; u32 itemoff; u32 start_block = BTRFS_SUPER_INFO_OFFSET / blocksize; + u16 item_size; + btrfs_set_super_generation(&super, 1); btrfs_set_super_blocknr(&super, start_block); btrfs_set_super_root(&super, start_block + 1); @@ -118,6 +121,9 @@ int mkfs(int fd, u64 num_blocks, u32 blocksize) btrfs_set_super_blocksize(&super, blocksize); btrfs_set_super_total_blocks(&super, num_blocks); btrfs_set_super_blocks_used(&super, start_block + 4); + btrfs_set_super_device_block_start(&super, 0); + btrfs_set_super_device_num_blocks(&super, num_blocks); + btrfs_set_super_device_root(&super, start_block + 2); uuid_generate(super.fsid); block = malloc(blocksize); @@ -146,20 +152,21 @@ int mkfs(int fd, u64 num_blocks, u32 blocksize) btrfs_set_inode_mode(inode_item, S_IFDIR | 0755); btrfs_set_root_dirid(&root_item, 0); - btrfs_set_root_blocknr(&root_item, start_block + 2); btrfs_set_root_refs(&root_item, 1); - itemoff = __BTRFS_LEAF_DATA_SIZE(blocksize) - sizeof(root_item); - btrfs_set_item_offset(&item, itemoff); - btrfs_set_item_size(&item, sizeof(root_item)); - btrfs_set_disk_key_objectid(&item.key, BTRFS_EXTENT_TREE_OBJECTID); btrfs_set_disk_key_offset(&item.key, 0); btrfs_set_disk_key_flags(&item.key, 0); + btrfs_set_item_size(&item, sizeof(root_item)); btrfs_set_disk_key_type(&item.key, BTRFS_ROOT_ITEM_KEY); + + itemoff = __BTRFS_LEAF_DATA_SIZE(blocksize) - sizeof(root_item); + btrfs_set_root_blocknr(&root_item, start_block + 3); + btrfs_set_item_offset(&item, itemoff); + btrfs_set_disk_key_objectid(&item.key, BTRFS_EXTENT_TREE_OBJECTID); memcpy(empty_leaf->items, &item, sizeof(item)); memcpy(btrfs_leaf_data(empty_leaf) + itemoff, &root_item, sizeof(root_item)); - btrfs_set_root_blocknr(&root_item, start_block + 3); + btrfs_set_root_blocknr(&root_item, start_block + 4); itemoff = itemoff - sizeof(root_item); btrfs_set_item_offset(&item, itemoff); btrfs_set_disk_key_objectid(&item.key, BTRFS_FS_TREE_OBJECTID); @@ -168,9 +175,31 @@ int mkfs(int fd, u64 num_blocks, u32 blocksize) &root_item, sizeof(root_item)); ret = pwrite(fd, empty_leaf, blocksize, (start_block + 1) * blocksize); - /* create the items for the extent tree */ + /* create the item for the dev tree */ btrfs_set_header_blocknr(&empty_leaf->header, start_block + 2); - btrfs_set_header_nritems(&empty_leaf->header, 4); + btrfs_set_header_nritems(&empty_leaf->header, 1); + btrfs_set_disk_key_objectid(&item.key, 0); + btrfs_set_disk_key_offset(&item.key, num_blocks); + btrfs_set_disk_key_flags(&item.key, 0); + btrfs_set_disk_key_type(&item.key, BTRFS_DEV_ITEM_KEY); + + item_size = sizeof(struct btrfs_device_item) + strlen(pathname); + itemoff = __BTRFS_LEAF_DATA_SIZE(blocksize) - item_size; + btrfs_set_item_offset(&item, itemoff); + btrfs_set_item_size(&item, item_size); + btrfs_set_device_pathlen(&dev_item, strlen(pathname)); + memcpy(empty_leaf->items, &item, sizeof(item)); + memcpy(btrfs_leaf_data(empty_leaf) + itemoff, &dev_item, + sizeof(dev_item)); + memcpy(btrfs_leaf_data(empty_leaf) + itemoff + sizeof(dev_item), + pathname, strlen(pathname)); + ret = pwrite(fd, empty_leaf, blocksize, (start_block + 2) * blocksize); + if (ret != blocksize) + return -1; + + /* create the items for the extent tree */ + btrfs_set_header_blocknr(&empty_leaf->header, start_block + 3); + btrfs_set_header_nritems(&empty_leaf->header, 5); /* item1, reserve blocks 0-16 */ btrfs_set_disk_key_objectid(&item.key, 0); @@ -195,7 +224,7 @@ int mkfs(int fd, u64 num_blocks, u32 blocksize) memcpy(btrfs_leaf_data(empty_leaf) + btrfs_item_offset(&item), &extent_item, btrfs_item_size(&item)); - /* item3, give block 18 to the extent root */ + /* item3, give block 18 to the dev root */ btrfs_set_disk_key_objectid(&item.key, start_block + 2); btrfs_set_disk_key_offset(&item.key, 1); itemoff = itemoff - sizeof(struct btrfs_extent_item); @@ -204,7 +233,7 @@ int mkfs(int fd, u64 num_blocks, u32 blocksize) memcpy(btrfs_leaf_data(empty_leaf) + btrfs_item_offset(&item), &extent_item, btrfs_item_size(&item)); - /* item5, give block 19 to the FS root */ + /* item4, give block 19 to the extent root */ btrfs_set_disk_key_objectid(&item.key, start_block + 3); btrfs_set_disk_key_offset(&item.key, 1); itemoff = itemoff - sizeof(struct btrfs_extent_item); @@ -212,14 +241,23 @@ int mkfs(int fd, u64 num_blocks, u32 blocksize) memcpy(empty_leaf->items + 3, &item, sizeof(item)); memcpy(btrfs_leaf_data(empty_leaf) + btrfs_item_offset(&item), &extent_item, btrfs_item_size(&item)); - ret = pwrite(fd, empty_leaf, blocksize, (start_block + 2) * blocksize); + + /* item5, give block 20 to the FS root */ + btrfs_set_disk_key_objectid(&item.key, start_block + 4); + btrfs_set_disk_key_offset(&item.key, 1); + itemoff = itemoff - sizeof(struct btrfs_extent_item); + btrfs_set_item_offset(&item, itemoff); + memcpy(empty_leaf->items + 4, &item, sizeof(item)); + memcpy(btrfs_leaf_data(empty_leaf) + btrfs_item_offset(&item), + &extent_item, btrfs_item_size(&item)); + ret = pwrite(fd, empty_leaf, blocksize, (start_block + 3) * blocksize); if (ret != blocksize) return -1; /* finally create the FS root */ - btrfs_set_header_blocknr(&empty_leaf->header, start_block + 3); + btrfs_set_header_blocknr(&empty_leaf->header, start_block + 4); btrfs_set_header_nritems(&empty_leaf->header, 0); - ret = pwrite(fd, empty_leaf, blocksize, (start_block + 3) * blocksize); + ret = pwrite(fd, empty_leaf, blocksize, (start_block + 4) * blocksize); if (ret != blocksize) return -1; return 0; @@ -248,6 +286,7 @@ int main(int ac, char **av) int ret; int i; char *buf = malloc(4096); + char *realpath_name; radix_tree_init(); @@ -287,14 +326,15 @@ int main(int ac, char **av) exit(1); } memset(buf, 0, 4096); - for(i = 0; i < 16; i++) { + for(i = 0; i < 64; i++) { ret = write(fd, buf, 4096); if (ret != 4096) { fprintf(stderr, "unable to zero fill device\n"); exit(1); } } - ret = mkfs(fd, block_count, 4096); + realpath_name = realpath(file, NULL); + ret = mkfs(fd, realpath_name, block_count, 4096); if (ret) { fprintf(stderr, "error during mkfs %d\n", ret); exit(1); diff --git a/print-tree.c b/print-tree.c index 49acb282..eb0c86b0 100644 --- a/print-tree.c +++ b/print-tree.c @@ -13,6 +13,7 @@ void btrfs_print_leaf(struct btrfs_root *root, struct btrfs_leaf *l) struct btrfs_extent_item *ei; struct btrfs_root_item *ri; struct btrfs_dir_item *di; + struct btrfs_device_item *devi; struct btrfs_inode_item *ii; struct btrfs_file_extent_item *fi; char *p; @@ -85,6 +86,13 @@ void btrfs_print_leaf(struct btrfs_root *root, struct btrfs_leaf *l) btrfs_file_extent_offset(fi), btrfs_file_extent_num_blocks(fi)); break; + case BTRFS_DEV_ITEM_KEY: + devi = btrfs_item_ptr(l, i, struct btrfs_device_item); + printf("\t\tdev namelen %u name %.*s\n", + btrfs_device_pathlen(devi), + btrfs_device_pathlen(devi), + (char *)(devi + 1)); + break; case BTRFS_STRING_ITEM_KEY: printf("\t\titem data %.*s\n", btrfs_item_size(item), btrfs_leaf_data(l) + btrfs_item_offset(item));