diff --git a/ctree.c b/ctree.c index 9f904620..eea7936a 100644 --- a/ctree.c +++ b/ctree.c @@ -1340,6 +1340,11 @@ static int noinline insert_new_root(struct btrfs_trans_handle *trans, write_extent_buffer(c, root->fs_info->fsid, (unsigned long)btrfs_header_fsid(c), BTRFS_FSID_SIZE); + + write_extent_buffer(c, root->fs_info->chunk_tree_uuid, + (unsigned long)btrfs_header_chunk_tree_uuid(c), + BTRFS_UUID_SIZE); + btrfs_set_node_key(c, &lower_key, 0); btrfs_set_node_blockptr(c, 0, lower->start); lower_gen = btrfs_header_generation(lower); @@ -1471,6 +1476,9 @@ static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root write_extent_buffer(split, root->fs_info->fsid, (unsigned long)btrfs_header_fsid(split), BTRFS_FSID_SIZE); + write_extent_buffer(split, root->fs_info->chunk_tree_uuid, + (unsigned long)btrfs_header_chunk_tree_uuid(split), + BTRFS_UUID_SIZE); mid = (c_nritems + 1) / 2; @@ -1941,6 +1949,10 @@ again: write_extent_buffer(right, root->fs_info->fsid, (unsigned long)btrfs_header_fsid(right), BTRFS_FSID_SIZE); + + write_extent_buffer(right, root->fs_info->chunk_tree_uuid, + (unsigned long)btrfs_header_chunk_tree_uuid(right), + BTRFS_UUID_SIZE); if (mid <= slot) { if (nritems == 1 || leaf_space_used(l, mid, nritems - mid) + space_needed > diff --git a/ctree.h b/ctree.h index 9c7f8a5d..fb0a6008 100644 --- a/ctree.h +++ b/ctree.h @@ -59,6 +59,7 @@ struct btrfs_trans_handle; * All files have objectids higher than this. */ #define BTRFS_FIRST_FREE_OBJECTID 256ULL +#define BTRFS_FIRST_CHUNK_TREE_OBJECTID 256ULL /* @@ -120,7 +121,7 @@ struct btrfs_mapping_tree { struct cache_tree cache_tree; }; -#define BTRFS_DEV_UUID_SIZE 16 +#define BTRFS_UUID_SIZE 16 struct btrfs_dev_item { /* the internal btrfs device id */ __le64 devid; @@ -143,17 +144,32 @@ struct btrfs_dev_item { /* type and info about this device */ __le64 type; + /* grouping information for allocation decisions */ + __le32 dev_group; + + /* seek speed 0-100 where 100 is fastest */ + u8 seek_speed; + + /* bandwidth 0-100 where 100 is fastest */ + u8 bandwidth; + /* btrfs generated uuid for this device */ - u8 uuid[BTRFS_DEV_UUID_SIZE]; + u8 uuid[BTRFS_UUID_SIZE]; } __attribute__ ((__packed__)); struct btrfs_stripe { __le64 devid; __le64 offset; + u8 dev_uuid[BTRFS_UUID_SIZE]; } __attribute__ ((__packed__)); struct btrfs_chunk { + /* size of this chunk in bytes */ + __le64 length; + + /* objectid of the root referencing this chunk */ __le64 owner; + __le64 stripe_len; __le64 type; @@ -188,10 +204,14 @@ static inline unsigned long btrfs_chunk_item_size(int num_stripes) * every tree block (leaf or node) starts with this header. */ struct btrfs_header { + /* these first four must match the super block */ u8 csum[BTRFS_CSUM_SIZE]; u8 fsid[BTRFS_FSID_SIZE]; /* FS specific uuid */ __le64 bytenr; /* which block this node is supposed to live in */ __le64 flags; + + /* allowed to be different from the super from here on down */ + u8 chunk_tree_uuid[BTRFS_UUID_SIZE]; __le64 generation; __le64 owner; __le32 nritems; @@ -223,6 +243,8 @@ struct btrfs_super_block { u8 fsid[BTRFS_FSID_SIZE]; /* FS specific uuid */ __le64 bytenr; /* this block number */ __le64 flags; + + /* allowed to be different from the btrfs_header from here own down */ __le64 magic; __le64 generation; __le64 root; @@ -311,14 +333,16 @@ struct btrfs_extent_ref { /* dev extents record free space on individual devices. The owner * field points back to the chunk allocation mapping tree that allocated - * the extent + * the extent. The chunk tree uuid field is a way to double check the owner */ struct btrfs_dev_extent { - __le64 owner; + __le64 chunk_tree; + __le64 chunk_objectid; + __le64 chunk_offset; __le64 length; + u8 chunk_tree_uuid[BTRFS_UUID_SIZE]; } __attribute__ ((__packed__)); - struct btrfs_inode_ref { __le16 name_len; /* name goes here */ @@ -411,7 +435,6 @@ struct btrfs_csum_item { struct btrfs_block_group_item { __le64 used; - __le64 chunk_tree; __le64 chunk_objectid; __le64 flags; } __attribute__ ((__packed__)); @@ -446,6 +469,7 @@ struct btrfs_device; struct btrfs_fs_devices; struct btrfs_fs_info { u8 fsid[BTRFS_FSID_SIZE]; + u8 chunk_tree_uuid[BTRFS_UUID_SIZE]; struct btrfs_root *fs_root; struct btrfs_root *extent_root; struct btrfs_root *tree_root; @@ -645,6 +669,9 @@ BTRFS_SETGET_FUNCS(device_io_align, struct btrfs_dev_item, io_align, 32); BTRFS_SETGET_FUNCS(device_io_width, struct btrfs_dev_item, io_width, 32); BTRFS_SETGET_FUNCS(device_sector_size, struct btrfs_dev_item, sector_size, 32); BTRFS_SETGET_FUNCS(device_id, struct btrfs_dev_item, devid, 64); +BTRFS_SETGET_FUNCS(device_group, struct btrfs_dev_item, dev_group, 32); +BTRFS_SETGET_FUNCS(device_seek_speed, struct btrfs_dev_item, seek_speed, 8); +BTRFS_SETGET_FUNCS(device_bandwidth, struct btrfs_dev_item, bandwidth, 8); BTRFS_SETGET_STACK_FUNCS(stack_device_type, struct btrfs_dev_item, type, 64); BTRFS_SETGET_STACK_FUNCS(stack_device_total_bytes, struct btrfs_dev_item, @@ -658,12 +685,19 @@ BTRFS_SETGET_STACK_FUNCS(stack_device_io_width, struct btrfs_dev_item, BTRFS_SETGET_STACK_FUNCS(stack_device_sector_size, struct btrfs_dev_item, sector_size, 32); BTRFS_SETGET_STACK_FUNCS(stack_device_id, struct btrfs_dev_item, devid, 64); +BTRFS_SETGET_STACK_FUNCS(stack_device_group, struct btrfs_dev_item, + dev_group, 32); +BTRFS_SETGET_STACK_FUNCS(stack_device_seek_speed, struct btrfs_dev_item, + seek_speed, 8); +BTRFS_SETGET_STACK_FUNCS(stack_device_bandwidth, struct btrfs_dev_item, + bandwidth, 8); static inline char *btrfs_device_uuid(struct btrfs_dev_item *d) { return (char *)d + offsetof(struct btrfs_dev_item, uuid); } +BTRFS_SETGET_FUNCS(chunk_length, struct btrfs_chunk, length, 64); BTRFS_SETGET_FUNCS(chunk_owner, struct btrfs_chunk, owner, 64); BTRFS_SETGET_FUNCS(chunk_stripe_len, struct btrfs_chunk, stripe_len, 64); BTRFS_SETGET_FUNCS(chunk_io_align, struct btrfs_chunk, io_align, 32); @@ -674,6 +708,12 @@ BTRFS_SETGET_FUNCS(chunk_num_stripes, struct btrfs_chunk, num_stripes, 16); BTRFS_SETGET_FUNCS(stripe_devid, struct btrfs_stripe, devid, 64); BTRFS_SETGET_FUNCS(stripe_offset, struct btrfs_stripe, offset, 64); +static inline char *btrfs_stripe_dev_uuid(struct btrfs_stripe *s) +{ + return (char *)s + offsetof(struct btrfs_stripe, dev_uuid); +} + +BTRFS_SETGET_STACK_FUNCS(stack_chunk_length, struct btrfs_chunk, length, 64); BTRFS_SETGET_STACK_FUNCS(stack_chunk_owner, struct btrfs_chunk, owner, 64); BTRFS_SETGET_STACK_FUNCS(stack_chunk_stripe_len, struct btrfs_chunk, stripe_len, 64); @@ -729,13 +769,10 @@ BTRFS_SETGET_STACK_FUNCS(block_group_used, struct btrfs_block_group_item, used, 64); BTRFS_SETGET_FUNCS(disk_block_group_used, struct btrfs_block_group_item, used, 64); -BTRFS_SETGET_STACK_FUNCS(block_group_chunk_tree, struct btrfs_block_group_item, - chunk_tree, 64); -BTRFS_SETGET_FUNCS(disk_block_group_chunk_tree, struct btrfs_block_group_item, - chunk_tree, 64); BTRFS_SETGET_STACK_FUNCS(block_group_chunk_objectid, struct btrfs_block_group_item, chunk_objectid, 64); -BTRFS_SETGET_FUNCS(disk_block_group_chunk_objecitd, + +BTRFS_SETGET_FUNCS(disk_block_group_chunk_objectid, struct btrfs_block_group_item, chunk_objectid, 64); BTRFS_SETGET_FUNCS(disk_block_group_flags, struct btrfs_block_group_item, flags, 64); @@ -822,9 +859,20 @@ BTRFS_SETGET_STACK_FUNCS(stack_timespec_nsec, struct btrfs_timespec, nsec, 32); /* struct btrfs_dev_extent */ -BTRFS_SETGET_FUNCS(dev_extent_owner, struct btrfs_dev_extent, owner, 64); +BTRFS_SETGET_FUNCS(dev_extent_chunk_tree, struct btrfs_dev_extent, + chunk_tree, 64); +BTRFS_SETGET_FUNCS(dev_extent_chunk_objectid, struct btrfs_dev_extent, + chunk_objectid, 64); +BTRFS_SETGET_FUNCS(dev_extent_chunk_offset, struct btrfs_dev_extent, + chunk_offset, 64); BTRFS_SETGET_FUNCS(dev_extent_length, struct btrfs_dev_extent, length, 64); +static inline u8 *btrfs_dev_extent_chunk_tree_uuid(struct btrfs_dev_extent *dev) +{ + unsigned long ptr = offsetof(struct btrfs_dev_extent, chunk_tree_uuid); + return (u8 *)((unsigned long)dev + ptr); +} + /* struct btrfs_extent_item */ BTRFS_SETGET_FUNCS(extent_refs, struct btrfs_extent_item, refs, 32); @@ -1068,6 +1116,12 @@ static inline u8 *btrfs_header_fsid(struct extent_buffer *eb) return (u8 *)ptr; } +static inline u8 *btrfs_header_chunk_tree_uuid(struct extent_buffer *eb) +{ + unsigned long ptr = offsetof(struct btrfs_header, chunk_tree_uuid); + return (u8 *)ptr; +} + static inline u8 *btrfs_super_fsid(struct extent_buffer *eb) { unsigned long ptr = offsetof(struct btrfs_super_block, fsid); @@ -1261,7 +1315,7 @@ int btrfs_free_block_groups(struct btrfs_fs_info *info); int btrfs_read_block_groups(struct btrfs_root *root); int btrfs_make_block_group(struct btrfs_trans_handle *trans, struct btrfs_root *root, u64 bytes_used, - u64 type, u64 chunk_tree, u64 chunk_objectid, + u64 type, u64 chunk_objectid, u64 chunk_offset, u64 size); u64 btrfs_hash_extent_ref(u64 root_objectid, u64 ref_generation, u64 owner, u64 owner_offset); diff --git a/disk-io.c b/disk-io.c index 6896bd78..3080e62a 100644 --- a/disk-io.c +++ b/disk-io.c @@ -577,6 +577,10 @@ struct btrfs_root *open_ctree_fd(int fp, const char *path, u64 sb_bytenr) BUG_ON(!chunk_root->node); + read_extent_buffer(chunk_root->node, fs_info->chunk_tree_uuid, + (unsigned long)btrfs_header_chunk_tree_uuid(chunk_root->node), + BTRFS_UUID_SIZE); + ret = btrfs_read_chunk_tree(chunk_root); BUG_ON(ret); @@ -634,7 +638,7 @@ int write_all_supers(struct btrfs_root *root) btrfs_set_device_sector_size(sb, dev_item, dev->sector_size); write_extent_buffer(sb, dev->uuid, (unsigned long)btrfs_device_uuid(dev_item), - BTRFS_DEV_UUID_SIZE); + BTRFS_UUID_SIZE); sb->fd = dev->fd; sb->dev_bytenr = BTRFS_SUPER_INFO_OFFSET; btrfs_set_header_flag(sb, BTRFS_HEADER_FLAG_WRITTEN); diff --git a/extent-tree.c b/extent-tree.c index f3c36e10..a7f04f4a 100644 --- a/extent-tree.c +++ b/extent-tree.c @@ -37,10 +37,6 @@ static int finish_current_insert(struct btrfs_trans_handle *trans, struct btrfs_root *extent_root); static int del_pending_extents(struct btrfs_trans_handle *trans, struct btrfs_root *extent_root); -int btrfs_make_block_group(struct btrfs_trans_handle *trans, - struct btrfs_root *root, u64 bytes_used, - u64 type, u64 chunk_tree, u64 chunk_objectid, - u64 size); static int cache_block_group(struct btrfs_root *root, struct btrfs_block_group_cache *block_group) @@ -959,7 +955,6 @@ int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans, ret = get_state_private(block_group_cache, start, &ptr); if (ret) break; - cache = (struct btrfs_block_group_cache *)(unsigned long)ptr; err = write_one_cache_group(trans, root, path, cache); @@ -1066,7 +1061,6 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans, ret = btrfs_alloc_chunk(trans, extent_root, &start, &num_bytes, flags); if (ret == -ENOSPC) { -printk("space info full %llu\n", (unsigned long long)flags); space_info->full = 1; return 0; } @@ -1074,8 +1068,7 @@ printk("space info full %llu\n", (unsigned long long)flags); BUG_ON(ret); ret = btrfs_make_block_group(trans, extent_root, 0, flags, - extent_root->fs_info->chunk_root->root_key.objectid, - start, num_bytes); + BTRFS_FIRST_CHUNK_TREE_OBJECTID, start, num_bytes); BUG_ON(ret); return 0; } @@ -2293,7 +2286,7 @@ error: int btrfs_make_block_group(struct btrfs_trans_handle *trans, struct btrfs_root *root, u64 bytes_used, - u64 type, u64 chunk_tree, u64 chunk_objectid, + u64 type, u64 chunk_objectid, u64 chunk_offset, u64 size) { int ret; @@ -2307,11 +2300,11 @@ int btrfs_make_block_group(struct btrfs_trans_handle *trans, cache = kzalloc(sizeof(*cache), GFP_NOFS); BUG_ON(!cache); - cache->key.objectid = chunk_objectid; + cache->key.objectid = chunk_offset; cache->key.offset = size; + btrfs_set_key_type(&cache->key, BTRFS_BLOCK_GROUP_ITEM_KEY); btrfs_set_block_group_used(&cache->item, bytes_used); - btrfs_set_block_group_chunk_tree(&cache->item, chunk_tree); btrfs_set_block_group_chunk_objectid(&cache->item, chunk_objectid); cache->flags = type; btrfs_set_block_group_flags(&cache->item, type); @@ -2321,12 +2314,12 @@ int btrfs_make_block_group(struct btrfs_trans_handle *trans, BUG_ON(ret); bit = block_group_state_bits(type); - set_extent_bits(block_group_cache, chunk_objectid, - chunk_objectid + size - 1, + set_extent_bits(block_group_cache, chunk_offset, + chunk_offset + size - 1, bit | EXTENT_LOCKED, GFP_NOFS); - set_state_private(block_group_cache, chunk_objectid, - (unsigned long)cache); + set_state_private(block_group_cache, chunk_offset, + (unsigned long)cache); ret = btrfs_insert_item(trans, extent_root, &cache->key, &cache->item, sizeof(cache->item)); BUG_ON(ret); diff --git a/mkfs.c b/mkfs.c index 8eabc41d..741edc67 100644 --- a/mkfs.c +++ b/mkfs.c @@ -82,16 +82,17 @@ static int make_root_dir(int fd, const char *device_name) { root->fs_info->force_system_allocs = 1; ret = btrfs_make_block_group(trans, root, bytes_used, BTRFS_BLOCK_GROUP_SYSTEM, - BTRFS_CHUNK_TREE_OBJECTID, + BTRFS_FIRST_CHUNK_TREE_OBJECTID, 0, BTRFS_MKFS_SYSTEM_GROUP_SIZE); BUG_ON(ret); + ret = btrfs_alloc_chunk(trans, root->fs_info->extent_root, &chunk_start, &chunk_size, BTRFS_BLOCK_GROUP_METADATA); BUG_ON(ret); ret = btrfs_make_block_group(trans, root, 0, BTRFS_BLOCK_GROUP_METADATA, - BTRFS_CHUNK_TREE_OBJECTID, + BTRFS_FIRST_CHUNK_TREE_OBJECTID, chunk_start, chunk_size); BUG_ON(ret); @@ -106,7 +107,7 @@ static int make_root_dir(int fd, const char *device_name) { BUG_ON(ret); ret = btrfs_make_block_group(trans, root, 0, BTRFS_BLOCK_GROUP_DATA, - BTRFS_CHUNK_TREE_OBJECTID, + BTRFS_FIRST_CHUNK_TREE_OBJECTID, chunk_start, chunk_size); BUG_ON(ret); @@ -186,7 +187,7 @@ static int create_one_raid_group(struct btrfs_trans_handle *trans, &chunk_start, &chunk_size, type); BUG_ON(ret); ret = btrfs_make_block_group(trans, root->fs_info->extent_root, 0, - type, BTRFS_CHUNK_TREE_OBJECTID, + type, BTRFS_FIRST_CHUNK_TREE_OBJECTID, chunk_start, chunk_size); BUG_ON(ret); return ret; diff --git a/print-tree.c b/print-tree.c index 6a4d0f11..f0757764 100644 --- a/print-tree.c +++ b/print-tree.c @@ -18,6 +18,7 @@ #include <stdio.h> #include <stdlib.h> +#include <uuid/uuid.h> #include "kerncompat.h" #include "radix-tree.h" #include "ctree.h" @@ -79,7 +80,8 @@ static void print_chunk(struct extent_buffer *eb, struct btrfs_chunk *chunk) { int num_stripes = btrfs_chunk_num_stripes(eb, chunk); int i; - printf("\t\tchunk owner %llu type %llu num_stripes %d\n", + printf("\t\tchunk length %llu owner %llu type %llu num_stripes %d\n", + (unsigned long long)btrfs_chunk_length(eb, chunk), (unsigned long long)btrfs_chunk_owner(eb, chunk), (unsigned long long)btrfs_chunk_type(eb, chunk), num_stripes); @@ -98,6 +100,28 @@ static void print_dev_item(struct extent_buffer *eb, (unsigned long long)btrfs_device_total_bytes(eb, dev_item), (unsigned long long)btrfs_device_bytes_used(eb, dev_item)); } + +static void print_uuids(struct extent_buffer *eb) +{ + char fs_uuid[37]; + char chunk_uuid[37]; + u8 disk_uuid[BTRFS_UUID_SIZE]; + + read_extent_buffer(eb, disk_uuid, (unsigned long)btrfs_header_fsid(eb), + BTRFS_FSID_SIZE); + + fs_uuid[36] = '\0'; + uuid_unparse(disk_uuid, fs_uuid); + + read_extent_buffer(eb, disk_uuid, + (unsigned long)btrfs_header_chunk_tree_uuid(eb), + BTRFS_UUID_SIZE); + + chunk_uuid[36] = '\0'; + uuid_unparse(disk_uuid, chunk_uuid); + printf("fs uuid %s\nchunk uuid %s\n", fs_uuid, chunk_uuid); +} + void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l) { int i; @@ -124,6 +148,7 @@ void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l) btrfs_leaf_free_space(root, l), (unsigned long long)btrfs_header_generation(l), (unsigned long long)btrfs_header_owner(l)); + print_uuids(l); fflush(stdout); for (i = 0 ; i < nr ; i++) { item = btrfs_item_nr(l, i); @@ -214,7 +239,7 @@ void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l) struct btrfs_block_group_item); read_extent_buffer(l, &bg_item, (unsigned long)bi, sizeof(bg_item)); - printf("\t\tblock group used %llu flags %llx\n", + printf("\t\tblock group used %llu flags %llu\n", (unsigned long long)btrfs_block_group_used(&bg_item), (unsigned long long)btrfs_block_group_flags(&bg_item)); break; @@ -228,9 +253,17 @@ void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l) case BTRFS_DEV_EXTENT_KEY: dev_extent = btrfs_item_ptr(l, i, struct btrfs_dev_extent); - printf("\t\tdev extent owner %llu length %llu\n", - (unsigned long long)btrfs_dev_extent_owner(l, dev_extent), - (unsigned long long)btrfs_dev_extent_length(l, dev_extent)); + printf("\t\tdev extent chunk_tree %llu\n" + "\t\tchunk objectid %llu chunk offset %llu " + "length %llu\n", + (unsigned long long) + btrfs_dev_extent_chunk_tree(l, dev_extent), + (unsigned long long) + btrfs_dev_extent_chunk_objectid(l, dev_extent), + (unsigned long long) + btrfs_dev_extent_chunk_offset(l, dev_extent), + (unsigned long long) + btrfs_dev_extent_length(l, dev_extent)); break; case BTRFS_STRING_ITEM_KEY: /* dirty, but it's simple */ @@ -241,6 +274,7 @@ void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l) fflush(stdout); } } + void btrfs_print_tree(struct btrfs_root *root, struct extent_buffer *eb) { int i; @@ -261,6 +295,7 @@ void btrfs_print_tree(struct btrfs_root *root, struct extent_buffer *eb) (u32)BTRFS_NODEPTRS_PER_BLOCK(root) - nr, (unsigned long long)btrfs_header_generation(eb), (unsigned long long)btrfs_header_owner(eb)); + print_uuids(eb); fflush(stdout); size = btrfs_level_size(root, btrfs_header_level(eb) - 1); for (i = 0; i < nr; i++) { diff --git a/utils.c b/utils.c index 0015ee27..0caa7085 100644 --- a/utils.c +++ b/utils.c @@ -68,6 +68,7 @@ int make_btrfs(int fd, char *device_name, struct btrfs_chunk *chunk; struct btrfs_dev_item *dev_item; struct btrfs_dev_extent *dev_extent; + u8 chunk_tree_uuid[BTRFS_UUID_SIZE]; u8 *ptr; int i; int ret; @@ -85,6 +86,10 @@ int make_btrfs(int fd, char *device_name, num_bytes = (num_bytes / sectorsize) * sectorsize; uuid_generate(super.fsid); + uuid_generate(super.dev_item.uuid); + + uuid_generate(chunk_tree_uuid); + btrfs_set_super_bytenr(&super, blocks[0]); btrfs_set_super_num_devices(&super, 1); strncpy((char *)&super.magic, BTRFS_MAGIC, sizeof(super.magic)); @@ -114,6 +119,10 @@ int make_btrfs(int fd, char *device_name, write_extent_buffer(buf, super.fsid, (unsigned long) btrfs_header_fsid(buf), BTRFS_FSID_SIZE); + write_extent_buffer(buf, chunk_tree_uuid, (unsigned long) + btrfs_header_chunk_tree_uuid(buf), + BTRFS_UUID_SIZE); + /* create the items for the root tree */ memset(&root_item, 0, sizeof(root_item)); inode_item = &root_item.inode; @@ -237,45 +246,10 @@ int make_btrfs(int fd, char *device_name, /* create the chunk tree */ nritems = 0; - item_size = btrfs_chunk_item_size(1); + item_size = sizeof(*dev_item); itemoff = __BTRFS_LEAF_DATA_SIZE(leafsize) - item_size; - /* first we have chunk 0 */ - btrfs_set_disk_key_objectid(&disk_key, 0); - btrfs_set_disk_key_offset(&disk_key, BTRFS_MKFS_SYSTEM_GROUP_SIZE); - btrfs_set_disk_key_type(&disk_key, BTRFS_CHUNK_ITEM_KEY); - btrfs_set_item_key(buf, &disk_key, nritems); - btrfs_set_item_offset(buf, btrfs_item_nr(buf, nritems), itemoff); - btrfs_set_item_size(buf, btrfs_item_nr(buf, nritems), item_size); - - chunk = btrfs_item_ptr(buf, nritems, struct btrfs_chunk); - btrfs_set_chunk_owner(buf, chunk, BTRFS_EXTENT_TREE_OBJECTID); - btrfs_set_chunk_stripe_len(buf, chunk, 64 * 1024); - btrfs_set_chunk_type(buf, chunk, BTRFS_BLOCK_GROUP_SYSTEM); - btrfs_set_chunk_io_align(buf, chunk, sectorsize); - btrfs_set_chunk_io_width(buf, chunk, sectorsize); - btrfs_set_chunk_sector_size(buf, chunk, sectorsize); - btrfs_set_chunk_num_stripes(buf, chunk, 1); - btrfs_set_stripe_devid_nr(buf, chunk, 0, 1); - btrfs_set_stripe_offset_nr(buf, chunk, 0, 0); - - /* copy the key for the chunk to the system array */ - ptr = super.sys_chunk_array; - array_size = sizeof(disk_key); - - memcpy(ptr, &disk_key, sizeof(disk_key)); - ptr += sizeof(disk_key); - - /* copy the chunk to the system array */ - read_extent_buffer(buf, ptr, (unsigned long)chunk, item_size); - array_size += item_size; - ptr += item_size; - btrfs_set_super_sys_array_size(&super, array_size); - - /* then device 1 (there is no device 0) */ - nritems++; - item_size = sizeof(*dev_item); - itemoff = itemoff - item_size; + /* first device 1 (there is no device 0) */ btrfs_set_disk_key_objectid(&disk_key, BTRFS_DEV_ITEMS_OBJECTID); btrfs_set_disk_key_offset(&disk_key, 1); btrfs_set_disk_key_type(&disk_key, BTRFS_DEV_ITEM_KEY); @@ -292,16 +266,55 @@ int make_btrfs(int fd, char *device_name, btrfs_set_device_io_width(buf, dev_item, sectorsize); btrfs_set_device_sector_size(buf, dev_item, sectorsize); btrfs_set_device_type(buf, dev_item, 0); - nritems++; - - uuid_generate(super.dev_item.uuid); write_extent_buffer(buf, super.dev_item.uuid, (unsigned long)btrfs_device_uuid(dev_item), - BTRFS_DEV_UUID_SIZE); + BTRFS_UUID_SIZE); read_extent_buffer(buf, &super.dev_item, (unsigned long)dev_item, sizeof(*dev_item)); + nritems++; + item_size = btrfs_chunk_item_size(1); + itemoff = itemoff - item_size; + + /* then we have chunk 0 */ + btrfs_set_disk_key_objectid(&disk_key, BTRFS_FIRST_CHUNK_TREE_OBJECTID); + btrfs_set_disk_key_offset(&disk_key, 0); + btrfs_set_disk_key_type(&disk_key, BTRFS_CHUNK_ITEM_KEY); + btrfs_set_item_key(buf, &disk_key, nritems); + btrfs_set_item_offset(buf, btrfs_item_nr(buf, nritems), itemoff); + btrfs_set_item_size(buf, btrfs_item_nr(buf, nritems), item_size); + + chunk = btrfs_item_ptr(buf, nritems, struct btrfs_chunk); + btrfs_set_chunk_length(buf, chunk, BTRFS_MKFS_SYSTEM_GROUP_SIZE); + btrfs_set_chunk_owner(buf, chunk, BTRFS_EXTENT_TREE_OBJECTID); + btrfs_set_chunk_stripe_len(buf, chunk, 64 * 1024); + btrfs_set_chunk_type(buf, chunk, BTRFS_BLOCK_GROUP_SYSTEM); + btrfs_set_chunk_io_align(buf, chunk, sectorsize); + btrfs_set_chunk_io_width(buf, chunk, sectorsize); + btrfs_set_chunk_sector_size(buf, chunk, sectorsize); + btrfs_set_chunk_num_stripes(buf, chunk, 1); + btrfs_set_stripe_devid_nr(buf, chunk, 0, 1); + btrfs_set_stripe_offset_nr(buf, chunk, 0, 0); + nritems++; + + write_extent_buffer(buf, super.dev_item.uuid, + (unsigned long)btrfs_stripe_dev_uuid(&chunk->stripe), + BTRFS_UUID_SIZE); + + /* copy the key for the chunk to the system array */ + ptr = super.sys_chunk_array; + array_size = sizeof(disk_key); + + memcpy(ptr, &disk_key, sizeof(disk_key)); + ptr += sizeof(disk_key); + + /* copy the chunk to the system array */ + read_extent_buffer(buf, ptr, (unsigned long)chunk, item_size); + array_size += item_size; + ptr += item_size; + btrfs_set_super_sys_array_size(&super, array_size); + btrfs_set_header_bytenr(buf, blocks[3]); btrfs_set_header_owner(buf, BTRFS_CHUNK_TREE_OBJECTID); btrfs_set_header_nritems(buf, nritems); @@ -321,7 +334,16 @@ int make_btrfs(int fd, char *device_name, btrfs_set_item_size(buf, btrfs_item_nr(buf, nritems), sizeof(struct btrfs_dev_extent)); dev_extent = btrfs_item_ptr(buf, nritems, struct btrfs_dev_extent); - btrfs_set_dev_extent_owner(buf, dev_extent, 0); + btrfs_set_dev_extent_chunk_tree(buf, dev_extent, + BTRFS_CHUNK_TREE_OBJECTID); + btrfs_set_dev_extent_chunk_objectid(buf, dev_extent, + BTRFS_FIRST_CHUNK_TREE_OBJECTID); + btrfs_set_dev_extent_chunk_offset(buf, dev_extent, 0); + + write_extent_buffer(buf, chunk_tree_uuid, + (unsigned long)btrfs_dev_extent_chunk_tree_uuid(dev_extent), + BTRFS_UUID_SIZE); + btrfs_set_dev_extent_length(buf, dev_extent, BTRFS_MKFS_SYSTEM_GROUP_SIZE); nritems++; @@ -464,7 +486,7 @@ int btrfs_add_to_fsid(struct btrfs_trans_handle *trans, btrfs_set_stack_device_sector_size(dev_item, device->sector_size); btrfs_set_stack_device_total_bytes(dev_item, device->total_bytes); btrfs_set_stack_device_bytes_used(dev_item, device->bytes_used); - memcpy(&dev_item->uuid, device->uuid, BTRFS_DEV_UUID_SIZE); + memcpy(&dev_item->uuid, device->uuid, BTRFS_UUID_SIZE); ret = pwrite(fd, buf, sectorsize, BTRFS_SUPER_INFO_OFFSET); BUG_ON(ret != sectorsize); diff --git a/volumes.c b/volumes.c index 29975672..9ecfdb82 100644 --- a/volumes.c +++ b/volumes.c @@ -325,7 +325,9 @@ error: int btrfs_alloc_dev_extent(struct btrfs_trans_handle *trans, struct btrfs_device *device, - u64 owner, u64 num_bytes, u64 *start) + u64 chunk_tree, u64 chunk_objectid, + u64 chunk_offset, + u64 num_bytes, u64 *start) { int ret; struct btrfs_path *path; @@ -353,7 +355,14 @@ int btrfs_alloc_dev_extent(struct btrfs_trans_handle *trans, leaf = path->nodes[0]; extent = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_dev_extent); - btrfs_set_dev_extent_owner(leaf, extent, owner); + btrfs_set_dev_extent_chunk_tree(leaf, extent, chunk_tree); + btrfs_set_dev_extent_chunk_objectid(leaf, extent, chunk_objectid); + btrfs_set_dev_extent_chunk_offset(leaf, extent, chunk_offset); + + write_extent_buffer(leaf, root->fs_info->chunk_tree_uuid, + (unsigned long)btrfs_dev_extent_chunk_tree_uuid(extent), + BTRFS_UUID_SIZE); + btrfs_set_dev_extent_length(leaf, extent, num_bytes); btrfs_mark_buffer_dirty(leaf); err: @@ -361,17 +370,18 @@ err: return ret; } -static int find_next_chunk(struct btrfs_root *root, u64 *objectid) +static int find_next_chunk(struct btrfs_root *root, u64 objectid, u64 *offset) { struct btrfs_path *path; int ret; struct btrfs_key key; + struct btrfs_chunk *chunk; struct btrfs_key found_key; path = btrfs_alloc_path(); BUG_ON(!path); - key.objectid = (u64)-1; + key.objectid = objectid; key.offset = (u64)-1; key.type = BTRFS_CHUNK_ITEM_KEY; @@ -383,11 +393,18 @@ static int find_next_chunk(struct btrfs_root *root, u64 *objectid) ret = btrfs_previous_item(root, path, 0, BTRFS_CHUNK_ITEM_KEY); if (ret) { - *objectid = 0; + *offset = 0; } else { btrfs_item_key_to_cpu(path->nodes[0], &found_key, path->slots[0]); - *objectid = found_key.objectid + found_key.offset; + if (found_key.objectid != objectid) + *offset = 0; + else { + chunk = btrfs_item_ptr(path->nodes[0], path->slots[0], + struct btrfs_chunk); + *offset = found_key.offset + + btrfs_chunk_length(path->nodes[0], chunk); + } } ret = 0; error: @@ -473,9 +490,12 @@ int btrfs_add_device(struct btrfs_trans_handle *trans, btrfs_set_device_sector_size(leaf, dev_item, device->sector_size); btrfs_set_device_total_bytes(leaf, dev_item, device->total_bytes); btrfs_set_device_bytes_used(leaf, dev_item, device->bytes_used); + btrfs_set_device_group(leaf, dev_item, 0); + btrfs_set_device_seek_speed(leaf, dev_item, 0); + btrfs_set_device_bandwidth(leaf, dev_item, 0); ptr = (unsigned long)btrfs_device_uuid(dev_item); - write_extent_buffer(leaf, device->uuid, ptr, BTRFS_DEV_UUID_SIZE); + write_extent_buffer(leaf, device->uuid, ptr, BTRFS_UUID_SIZE); btrfs_mark_buffer_dirty(leaf); ret = 0; @@ -633,7 +653,10 @@ again: return -ENOSPC; } - ret = find_next_chunk(chunk_root, &key.objectid); + key.objectid = BTRFS_FIRST_CHUNK_TREE_OBJECTID; + key.type = BTRFS_CHUNK_ITEM_KEY; + ret = find_next_chunk(chunk_root, BTRFS_FIRST_CHUNK_TREE_OBJECTID, + &key.offset); if (ret) return ret; @@ -655,8 +678,9 @@ again: *num_bytes = calc_size * num_stripes; index = 0; -printk("new chunk type %Lu start %Lu size %Lu\n", type, key.objectid, *num_bytes); +printk("new chunk type %Lu start %Lu size %Lu\n", type, key.offset, *num_bytes); while(index < num_stripes) { + struct btrfs_stripe *stripe; BUG_ON(list_empty(&private_devs)); cur = private_devs.next; device = list_entry(cur, struct btrfs_device, dev_list); @@ -667,8 +691,9 @@ printk("new chunk type %Lu start %Lu size %Lu\n", type, key.objectid, *num_bytes list_move_tail(&device->dev_list, dev_list); ret = btrfs_alloc_dev_extent(trans, device, - key.objectid, - calc_size, &dev_offset); + info->chunk_root->root_key.objectid, + BTRFS_FIRST_CHUNK_TREE_OBJECTID, key.offset, + calc_size, &dev_offset); BUG_ON(ret); printk("\talloc chunk size %llu from dev %llu phys %llu\n", (unsigned long long)calc_size, @@ -680,16 +705,17 @@ printk("\talloc chunk size %llu from dev %llu phys %llu\n", map->stripes[index].dev = device; map->stripes[index].physical = dev_offset; - btrfs_set_stack_stripe_devid(stripes + index, device->devid); - btrfs_set_stack_stripe_offset(stripes + index, dev_offset); + stripe = stripes + index; + btrfs_set_stack_stripe_devid(stripe, device->devid); + btrfs_set_stack_stripe_offset(stripe, dev_offset); + memcpy(stripe->dev_uuid, device->uuid, BTRFS_UUID_SIZE); physical = dev_offset; index++; } BUG_ON(!list_empty(&private_devs)); - /* key.objectid was set above */ - key.offset = *num_bytes; - key.type = BTRFS_CHUNK_ITEM_KEY; + /* key was set above */ + btrfs_set_stack_chunk_length(chunk, *num_bytes); btrfs_set_stack_chunk_owner(chunk, extent_root->root_key.objectid); btrfs_set_stack_chunk_stripe_len(chunk, stripe_len); btrfs_set_stack_chunk_type(chunk, type); @@ -707,10 +733,10 @@ printk("\talloc chunk size %llu from dev %llu phys %llu\n", ret = btrfs_insert_item(trans, chunk_root, &key, chunk, btrfs_chunk_item_size(num_stripes)); BUG_ON(ret); - *start = key.objectid; + *start = key.offset;; - map->ce.start = key.objectid; - map->ce.size = key.offset; + map->ce.start = key.offset; + map->ce.size = *num_bytes; ret = insert_existing_cache_extent( &extent_root->fs_info->mapping_tree.cache_tree, @@ -928,8 +954,8 @@ static int read_one_chunk(struct btrfs_root *root, struct btrfs_key *key, int ret; int i; - logical = key->objectid; - length = key->offset; + logical = key->offset; + length = btrfs_chunk_length(leaf, chunk); if (logical < BTRFS_SUPER_INFO_OFFSET + BTRFS_SUPER_INFO_SIZE) { super_offset_diff = BTRFS_SUPER_INFO_OFFSET + @@ -991,7 +1017,7 @@ static int fill_device_from_item(struct extent_buffer *leaf, device->sector_size = btrfs_device_sector_size(leaf, dev_item); ptr = (unsigned long)btrfs_device_uuid(dev_item); - read_extent_buffer(leaf, device->uuid, ptr, BTRFS_DEV_UUID_SIZE); + read_extent_buffer(leaf, device->uuid, ptr, BTRFS_UUID_SIZE); return 0; } diff --git a/volumes.h b/volumes.h index b6edc542..07d1c0a3 100644 --- a/volumes.h +++ b/volumes.h @@ -50,7 +50,7 @@ struct btrfs_device { u64 type; /* physical drive uuid (or lvm uuid) */ - u8 uuid[BTRFS_DEV_UUID_SIZE]; + u8 uuid[BTRFS_UUID_SIZE]; }; struct btrfs_fs_devices { @@ -82,7 +82,9 @@ struct btrfs_multi_bio { int btrfs_alloc_dev_extent(struct btrfs_trans_handle *trans, struct btrfs_device *device, - u64 owner, u64 num_bytes, u64 *start); + u64 chunk_tree, u64 chunk_objectid, + u64 chunk_offset, + u64 num_bytes, u64 *start); int btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, u64 logical, u64 *length, struct btrfs_multi_bio **multi_ret, int mirror_num);