early support for multiple devices
authorChris Mason <chris.mason@oracle.com>
Wed, 11 Apr 2007 17:57:55 +0000 (13:57 -0400)
committerDavid Woodhouse <dwmw2@hera.kernel.org>
Wed, 11 Apr 2007 17:57:55 +0000 (13:57 -0400)
Makefile
ctree.h
debug-tree.c
disk-io.c
disk-io.h
mkfs.c
print-tree.c

index 219ce80..7058b08 100644 (file)
--- 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 8d4ba19..edd965f 100644 (file)
--- 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;
@@ -301,10 +311,15 @@ 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) + \
index 9699e3c..229546a 100644 (file)
@@ -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;
index 448482f..dff3bd5 100644 (file)
--- 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);
index d888cf5..21f353a 100644 (file)
--- 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 8148259..58e754b 100644 (file)
--- 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);
index 49acb28..eb0c86b 100644 (file)
@@ -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));