#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
__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__));
/*
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;
#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)
{
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;
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) + \
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;
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);
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);
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);
&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);
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);
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);
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;
int ret;
int i;
char *buf = malloc(4096);
+ char *realpath_name;
radix_tree_init();
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);