summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2008-04-15 15:42:08 -0400
committerDavid Woodhouse <dwmw2@hera.kernel.org>2008-04-15 15:42:08 -0400
commit951fd7371c5719f0491e0a8a524cf5be43729412 (patch)
tree9930eafb1f6d38600e101c3c965b6a6723254000
parent7e7628ec4ebec9a5046025b4a139d55ac3a69d49 (diff)
Add chunk uuids and update multi-device back references
Block headers now store the chunk tree uuid Chunk items records the device uuid for each stripes Device extent items record better back refs to the chunk tree Block groups record better back refs to the chunk tree The chunk tree format has also changed. The objectid of BTRFS_CHUNK_ITEM_KEY used to be the logical offset of the chunk. Now it is a chunk tree id, with the logical offset being stored in the offset field of the key. This allows a single chunk tree to record multiple logical address spaces, upping the number of bytes indexed by a chunk tree from 2^64 to 2^128.
-rw-r--r--ctree.c12
-rw-r--r--ctree.h80
-rw-r--r--disk-io.c6
-rw-r--r--extent-tree.c23
-rw-r--r--mkfs.c9
-rw-r--r--print-tree.c45
-rw-r--r--utils.c94
-rw-r--r--volumes.c70
-rw-r--r--volumes.h6
9 files changed, 247 insertions, 98 deletions
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,18 +246,47 @@ 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);
+ /* 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);
+ 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);
+
+ dev_item = btrfs_item_ptr(buf, nritems, struct btrfs_dev_item);
+ btrfs_set_device_id(buf, dev_item, 1);
+ btrfs_set_device_total_bytes(buf, dev_item, num_bytes);
+ btrfs_set_device_bytes_used(buf, dev_item,
+ BTRFS_MKFS_SYSTEM_GROUP_SIZE);
+ btrfs_set_device_io_align(buf, dev_item, sectorsize);
+ 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);
+
+ write_extent_buffer(buf, super.dev_item.uuid,
+ (unsigned long)btrfs_device_uuid(dev_item),
+ 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);
@@ -258,6 +296,11 @@ int make_btrfs(int fd, char *device_name,
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;
@@ -272,36 +315,6 @@ int make_btrfs(int fd, char *device_name,
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;
- 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);
- 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);
-
- dev_item = btrfs_item_ptr(buf, nritems, struct btrfs_dev_item);
- btrfs_set_device_id(buf, dev_item, 1);
- btrfs_set_device_total_bytes(buf, dev_item, num_bytes);
- btrfs_set_device_bytes_used(buf, dev_item,
- BTRFS_MKFS_SYSTEM_GROUP_SIZE);
- btrfs_set_device_io_align(buf, dev_item, sectorsize);
- 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);
- read_extent_buffer(buf, &super.dev_item, (unsigned long)dev_item,
- sizeof(*dev_item));
-
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);