Switch to byte granular allocations

master
Chris Mason 2007-10-15 16:25:14 -04:00 committed by David Woodhouse
parent 08c66b7738
commit 38f79f9077
10 changed files with 423 additions and 319 deletions

View File

@ -12,7 +12,8 @@ INSTALL= install
prefix ?= /usr/local
bindir = $(prefix)/bin
progs = btrfsctl btrfsck mkfs.btrfs debug-tree
#progs = btrfsctl btrfsck mkfs.btrfs debug-tree
progs = btrfsctl mkfs.btrfs debug-tree
# make C=1 to enable sparse
ifdef C

View File

@ -78,12 +78,12 @@ static int check_leaf(struct btrfs_root *root,
if (btrfs_header_level(&leaf->header) != 0) {
fprintf(stderr, "leaf is not a leaf %llu\n",
(unsigned long long)btrfs_header_blocknr(&leaf->header));
(unsigned long long)btrfs_header_bytenr(&leaf->header));
return 1;
}
if (btrfs_leaf_free_space(root, leaf) < 0) {
fprintf(stderr, "leaf free space incorrect %llu %d\n",
(unsigned long long)btrfs_header_blocknr(&leaf->header),
(unsigned long long)btrfs_header_bytenr(&leaf->header),
btrfs_leaf_free_space(root, leaf));
return 1;
}
@ -94,7 +94,7 @@ static int check_leaf(struct btrfs_root *root,
if (parent_key->type && memcmp(parent_key, &leaf->items[0].key,
sizeof(struct btrfs_disk_key))) {
fprintf(stderr, "leaf parent key incorrect %llu\n",
(unsigned long long)btrfs_header_blocknr(&leaf->header));
(unsigned long long)btrfs_header_bytenr(&leaf->header));
return 1;
}
for (i = 0; nritems > 1 && i < nritems - 2; i++) {

97
ctree.c
View File

@ -64,9 +64,9 @@ static int btrfs_cow_block(struct btrfs_trans_handle *trans, struct btrfs_root
*cow_ret = buf;
return 0;
}
cow = btrfs_alloc_free_block(trans, root);
memcpy(&cow->node, &buf->node, root->sectorsize);
btrfs_set_header_blocknr(&cow->node.header, cow->blocknr);
cow = btrfs_alloc_free_block(trans, root, buf->size);
memcpy(&cow->node, &buf->node, buf->size);
btrfs_set_header_bytenr(&cow->node.header, cow->bytenr);
btrfs_set_header_owner(&cow->node.header, root->root_key.objectid);
*cow_ret = cow;
btrfs_inc_ref(trans, root, buf);
@ -74,13 +74,14 @@ static int btrfs_cow_block(struct btrfs_trans_handle *trans, struct btrfs_root
root->node = cow;
cow->count++;
if (buf != root->commit_root)
btrfs_free_extent(trans, root, buf->blocknr, 1, 1);
btrfs_free_extent(trans, root, buf->bytenr,
buf->size, 1);
btrfs_block_release(root, buf);
} else {
btrfs_set_node_blockptr(&parent->node, parent_slot,
cow->blocknr);
cow->bytenr);
BUG_ON(list_empty(&parent->dirty));
btrfs_free_extent(trans, root, buf->blocknr, 1, 1);
btrfs_free_extent(trans, root, buf->bytenr, buf->size, 1);
}
btrfs_block_release(root, buf);
return 0;
@ -178,7 +179,7 @@ static int check_node(struct btrfs_root *root, struct btrfs_path *path,
BUG_ON(memcmp(parent_key, &node->ptrs[0].key,
sizeof(struct btrfs_disk_key)));
BUG_ON(btrfs_node_blockptr(parent, parent_slot) !=
btrfs_header_blocknr(&node->header));
btrfs_header_bytenr(&node->header));
}
BUG_ON(nritems > BTRFS_NODEPTRS_PER_BLOCK(root));
for (i = 0; nritems > 1 && i < nritems - 2; i++) {
@ -212,7 +213,7 @@ static int check_leaf(struct btrfs_root *root, struct btrfs_path *path,
BUG_ON(memcmp(parent_key, &leaf->items[0].key,
sizeof(struct btrfs_disk_key)));
BUG_ON(btrfs_node_blockptr(parent, parent_slot) !=
btrfs_header_blocknr(&leaf->header));
btrfs_header_bytenr(&leaf->header));
}
for (i = 0; nritems > 1 && i < nritems - 2; i++) {
struct btrfs_key cpukey;
@ -300,11 +301,13 @@ static struct btrfs_buffer *read_node_slot(struct btrfs_root *root,
int slot)
{
struct btrfs_node *node = &parent_buf->node;
int level = btrfs_header_level(&node->header);
if (slot < 0)
return NULL;
if (slot >= btrfs_header_nritems(&node->header))
return NULL;
return read_tree_block(root, btrfs_node_blockptr(node, slot));
return read_tree_block(root, btrfs_node_blockptr(node, slot),
btrfs_level_size(root, level - 1));
}
static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root
@ -341,7 +344,7 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root
*/
if (!parent_buf) {
struct btrfs_buffer *child;
u64 blocknr = mid_buf->blocknr;
u64 bytenr = mid_buf->bytenr;
if (btrfs_header_nritems(&mid->header) != 1)
return 0;
@ -356,7 +359,8 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root
/* once for the root ptr */
btrfs_block_release(root, mid_buf);
clean_tree_block(trans, root, mid_buf);
return btrfs_free_extent(trans, root, blocknr, 1, 1);
return btrfs_free_extent(trans, root, bytenr,
root->nodesize, 1);
}
parent = &parent_buf->node;
@ -389,7 +393,7 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root
if (wret < 0)
ret = wret;
if (btrfs_header_nritems(&right->header) == 0) {
u64 blocknr = right_buf->blocknr;
u64 bytenr = right_buf->bytenr;
btrfs_block_release(root, right_buf);
clean_tree_block(trans, root, right_buf);
right_buf = NULL;
@ -398,7 +402,8 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root
1);
if (wret)
ret = wret;
wret = btrfs_free_extent(trans, root, blocknr, 1, 1);
wret = btrfs_free_extent(trans, root, bytenr,
root->nodesize, 1);
if (wret)
ret = wret;
} else {
@ -426,7 +431,7 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root
}
if (btrfs_header_nritems(&mid->header) == 0) {
/* we've managed to empty the middle node, drop it */
u64 blocknr = mid_buf->blocknr;
u64 bytenr = mid_buf->bytenr;
btrfs_block_release(root, mid_buf);
clean_tree_block(trans, root, mid_buf);
mid_buf = NULL;
@ -434,7 +439,8 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root
wret = del_ptr(trans, root, path, level + 1, pslot);
if (wret)
ret = wret;
wret = btrfs_free_extent(trans, root, blocknr, 1, 1);
wret = btrfs_free_extent(trans, root, bytenr,
root->nodesize, 1);
if (wret)
ret = wret;
} else {
@ -539,7 +545,9 @@ again:
slot = p->slots[level];
BUG_ON(btrfs_header_nritems(&c->header) == 1);
}
b = read_tree_block(root, btrfs_node_blockptr(c, slot));
b = read_tree_block(root,
btrfs_node_blockptr(c, slot),
btrfs_level_size(root, level - 1));
} else {
struct btrfs_leaf *l = (struct btrfs_leaf *)c;
p->slots[level] = slot;
@ -696,22 +704,24 @@ static int insert_new_root(struct btrfs_trans_handle *trans, struct btrfs_root
BUG_ON(path->nodes[level]);
BUG_ON(path->nodes[level-1] != root->node);
t = btrfs_alloc_free_block(trans, root);
t = btrfs_alloc_free_block(trans, root, root->nodesize);
c = &t->node;
memset(c, 0, root->sectorsize);
memset(c, 0, root->nodesize);
btrfs_set_header_nritems(&c->header, 1);
btrfs_set_header_level(&c->header, level);
btrfs_set_header_blocknr(&c->header, t->blocknr);
btrfs_set_header_bytenr(&c->header, t->bytenr);
btrfs_set_header_owner(&c->header, root->root_key.objectid);
memcpy(c->header.fsid, root->fs_info->disk_super->fsid,
sizeof(c->header.fsid));
lower = &path->nodes[level-1]->node;
if (btrfs_is_leaf(lower))
lower_key = &((struct btrfs_leaf *)lower)->items[0].key;
else
lower_key = &lower->ptrs[0].key;
memcpy(&c->ptrs[0].key, lower_key, sizeof(struct btrfs_disk_key));
btrfs_set_node_blockptr(c, 0, path->nodes[level - 1]->blocknr);
btrfs_set_node_blockptr(c, 0, path->nodes[level - 1]->bytenr);
/* the super has an extra ref to root->node */
btrfs_block_release(root, root->node);
root->node = t;
@ -726,13 +736,13 @@ static int insert_new_root(struct btrfs_trans_handle *trans, struct btrfs_root
* the node should have enough room for the pointer already
*
* slot and level indicate where you want the key to go, and
* blocknr is the block the key points to.
* bytenr is the block the key points to.
*
* returns zero on success and < 0 on any error
*/
static int insert_ptr(struct btrfs_trans_handle *trans, struct btrfs_root
*root, struct btrfs_path *path, struct btrfs_disk_key
*key, u64 blocknr, int slot, int level)
*key, u64 bytenr, int slot, int level)
{
struct btrfs_node *lower;
int nritems;
@ -749,7 +759,7 @@ static int insert_ptr(struct btrfs_trans_handle *trans, struct btrfs_root
(nritems - slot) * sizeof(struct btrfs_key_ptr));
}
memcpy(&lower->ptrs[slot].key, key, sizeof(struct btrfs_disk_key));
btrfs_set_node_blockptr(lower, slot, blocknr);
btrfs_set_node_blockptr(lower, slot, bytenr);
btrfs_set_header_nritems(&lower->header, nritems + 1);
BUG_ON(list_empty(&path->nodes[level]->dirty));
return 0;
@ -785,11 +795,11 @@ static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root
return ret;
}
c_nritems = btrfs_header_nritems(&c->header);
split_buffer = btrfs_alloc_free_block(trans, root);
split_buffer = btrfs_alloc_free_block(trans, root, root->nodesize);
split = &split_buffer->node;
btrfs_set_header_flags(&split->header, btrfs_header_flags(&c->header));
btrfs_set_header_level(&split->header, btrfs_header_level(&c->header));
btrfs_set_header_blocknr(&split->header, split_buffer->blocknr);
btrfs_set_header_bytenr(&split->header, split_buffer->bytenr);
btrfs_set_header_owner(&split->header, root->root_key.objectid);
memcpy(split->header.fsid, root->fs_info->disk_super->fsid,
sizeof(split->header.fsid));
@ -802,7 +812,7 @@ static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root
BUG_ON(list_empty(&t->dirty));
wret = insert_ptr(trans, root, path, &split->ptrs[0].key,
split_buffer->blocknr, path->slots[level + 1] + 1,
split_buffer->bytenr, path->slots[level + 1] + 1,
level + 1);
if (wret)
ret = wret;
@ -850,8 +860,9 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root
if (slot >= btrfs_header_nritems(&upper->node.header) - 1) {
return 1;
}
right_buf = read_tree_block(root, btrfs_node_blockptr(&upper->node,
slot + 1));
right_buf = read_tree_block(root,
btrfs_node_blockptr(&upper->node, slot + 1),
root->leafsize);
right = &right_buf->leaf;
free_space = btrfs_leaf_free_space(root, right);
if (free_space < data_size + sizeof(struct btrfs_item)) {
@ -956,8 +967,9 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root
if (!path->nodes[1]) {
return 1;
}
t = read_tree_block(root, btrfs_node_blockptr(&path->nodes[1]->node,
slot - 1));
t = read_tree_block(root,
btrfs_node_blockptr(&path->nodes[1]->node, slot - 1),
root->leafsize);
left = &t->leaf;
free_space = btrfs_leaf_free_space(root, left);
if (free_space < data_size + sizeof(struct btrfs_item)) {
@ -1098,7 +1110,7 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root
slot = path->slots[0];
nritems = btrfs_header_nritems(&l->header);
mid = (nritems + 1)/ 2;
right_buffer = btrfs_alloc_free_block(trans, root);
right_buffer = btrfs_alloc_free_block(trans, root, root->leafsize);
BUG_ON(!right_buffer);
BUG_ON(mid == nritems);
right = &right_buffer->leaf;
@ -1115,7 +1127,7 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root
BUG();
}
btrfs_set_header_nritems(&right->header, nritems - mid);
btrfs_set_header_blocknr(&right->header, right_buffer->blocknr);
btrfs_set_header_bytenr(&right->header, right_buffer->bytenr);
btrfs_set_header_level(&right->header, 0);
btrfs_set_header_owner(&right->header, root->root_key.objectid);
memcpy(right->header.fsid, root->fs_info->disk_super->fsid,
@ -1138,7 +1150,7 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root
btrfs_set_header_nritems(&l->header, mid);
ret = 0;
wret = insert_ptr(trans, root, path, &right->items[0].key,
right_buffer->blocknr, path->slots[1] + 1, 1);
right_buffer->bytenr, path->slots[1] + 1, 1);
if (wret)
ret = wret;
BUG_ON(list_empty(&right_buffer->dirty));
@ -1350,7 +1362,8 @@ int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root,
if (wret)
ret = wret;
wret = btrfs_free_extent(trans, root,
leaf_buf->blocknr, 1, 1);
leaf_buf->bytenr,
leaf_buf->size, 1);
if (wret)
ret = wret;
}
@ -1382,14 +1395,14 @@ int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root,
ret = wret;
}
if (btrfs_header_nritems(&leaf->header) == 0) {
u64 blocknr = leaf_buf->blocknr;
u64 bytenr = leaf_buf->bytenr;
clean_tree_block(trans, root, leaf_buf);
wret = del_ptr(trans, root, path, 1, slot);
if (wret)
ret = wret;
wret = btrfs_free_extent(trans, root, bytenr,
leaf_buf->size, 1);
btrfs_block_release(root, leaf_buf);
wret = btrfs_free_extent(trans, root, blocknr,
1, 1);
if (wret)
ret = wret;
} else {
@ -1461,7 +1474,7 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path)
{
int slot;
int level = 1;
u64 blocknr;
u64 bytenr;
struct btrfs_buffer *c;
struct btrfs_buffer *next = NULL;
@ -1474,10 +1487,11 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path)
level++;
continue;
}
blocknr = btrfs_node_blockptr(&c->node, slot);
bytenr = btrfs_node_blockptr(&c->node, slot);
if (next)
btrfs_block_release(root, next);
next = read_tree_block(root, blocknr);
next = read_tree_block(root, bytenr,
btrfs_level_size(root, level - 1));
break;
}
path->slots[level] = slot;
@ -1490,7 +1504,8 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path)
if (!level)
break;
next = read_tree_block(root,
btrfs_node_blockptr(&next->node, 0));
btrfs_node_blockptr(&next->node, 0),
btrfs_level_size(root, level - 1));
}
return 0;
}

122
ctree.h
View File

@ -86,7 +86,7 @@ struct btrfs_key {
struct btrfs_header {
u8 csum[BTRFS_CSUM_SIZE];
u8 fsid[16]; /* FS specific uuid */
__le64 blocknr; /* which block this node is supposed to live in */
__le64 bytenr; /* which block this node is supposed to live in */
__le64 generation;
__le64 owner;
__le32 nritems;
@ -110,16 +110,17 @@ struct btrfs_super_block {
u8 csum[BTRFS_CSUM_SIZE];
/* the first 3 fields must match struct btrfs_header */
u8 fsid[16]; /* FS specific uuid */
__le64 blocknr; /* this block number */
__le64 bytenr; /* this block number */
__le64 magic;
__le64 generation;
__le64 root;
__le64 total_blocks;
__le64 blocks_used;
__le64 total_bytes;
__le64 bytes_used;
__le64 root_dir_objectid;
__le32 sectorsize;
__le32 nodesize;
__le32 leafsize;
u8 root_level;
} __attribute__ ((__packed__));
/*
@ -222,13 +223,14 @@ struct btrfs_dir_item {
struct btrfs_root_item {
struct btrfs_inode_item inode;
__le64 root_dirid;
__le64 blocknr;
__le64 block_limit;
__le64 blocks_used;
__le64 bytenr;
__le64 byte_limit;
__le64 bytes_used;
__le32 flags;
__le32 refs;
struct btrfs_disk_key drop_progress;
u8 drop_level;
u8 level;
} __attribute__ ((__packed__));
#define BTRFS_FILE_EXTENT_REG 0
@ -241,8 +243,8 @@ struct btrfs_file_extent_item {
* disk space consumed by the extent, checksum blocks are included
* in these numbers
*/
__le64 disk_blocknr;
__le64 disk_num_blocks;
__le64 disk_bytenr;
__le64 disk_num_bytes;
/*
* the logical offset in file blocks (no csums)
* this extent record is for. This allows a file extent to point
@ -254,7 +256,7 @@ struct btrfs_file_extent_item {
/*
* the logical number of file blocks (no csums included)
*/
__le64 num_blocks;
__le64 num_bytes;
} __attribute__ ((__packed__));
struct btrfs_csum_item {
@ -670,14 +672,14 @@ static inline void btrfs_set_key_type(struct btrfs_key *key, u32 val)
key->type = val;
}
static inline u64 btrfs_header_blocknr(struct btrfs_header *h)
static inline u64 btrfs_header_bytenr(struct btrfs_header *h)
{
return le64_to_cpu(h->blocknr);
return le64_to_cpu(h->bytenr);
}
static inline void btrfs_set_header_blocknr(struct btrfs_header *h, u64 blocknr)
static inline void btrfs_set_header_bytenr(struct btrfs_header *h, u64 bytenr)
{
h->blocknr = cpu_to_le64(blocknr);
h->bytenr = cpu_to_le64(bytenr);
}
static inline u64 btrfs_header_generation(struct btrfs_header *h)
@ -738,14 +740,14 @@ static inline int btrfs_is_leaf(struct btrfs_node *n)
return (btrfs_header_level(&n->header) == 0);
}
static inline u64 btrfs_root_blocknr(struct btrfs_root_item *item)
static inline u64 btrfs_root_bytenr(struct btrfs_root_item *item)
{
return le64_to_cpu(item->blocknr);
return le64_to_cpu(item->bytenr);
}
static inline void btrfs_set_root_blocknr(struct btrfs_root_item *item, u64 val)
static inline void btrfs_set_root_bytenr(struct btrfs_root_item *item, u64 val)
{
item->blocknr = cpu_to_le64(val);
item->bytenr = cpu_to_le64(val);
}
static inline u64 btrfs_root_dirid(struct btrfs_root_item *item)
@ -778,25 +780,25 @@ static inline void btrfs_set_root_flags(struct btrfs_root_item *item, u32 val)
item->flags = cpu_to_le32(val);
}
static inline void btrfs_set_root_blocks_used(struct btrfs_root_item *item,
static inline void btrfs_set_root_bytes_used(struct btrfs_root_item *item,
u64 val)
{
item->blocks_used = cpu_to_le64(val);
item->bytes_used = cpu_to_le64(val);
}
static inline u64 btrfs_root_blocks_used(struct btrfs_root_item *item)
static inline u64 btrfs_root_bytes_used(struct btrfs_root_item *item)
{
return le64_to_cpu(item->blocks_used);
return le64_to_cpu(item->bytes_used);
}
static inline u64 btrfs_super_blocknr(struct btrfs_super_block *s)
static inline u64 btrfs_super_bytenr(struct btrfs_super_block *s)
{
return le64_to_cpu(s->blocknr);
return le64_to_cpu(s->bytenr);
}
static inline void btrfs_set_super_blocknr(struct btrfs_super_block *s, u64 val)
static inline void btrfs_set_super_bytenr(struct btrfs_super_block *s, u64 val)
{
s->blocknr = cpu_to_le64(val);
s->bytenr = cpu_to_le64(val);
}
static inline u64 btrfs_super_generation(struct btrfs_super_block *s)
@ -810,6 +812,17 @@ static inline void btrfs_set_super_generation(struct btrfs_super_block *s,
s->generation = cpu_to_le64(val);
}
static inline u8 btrfs_super_root_level(struct btrfs_super_block *s)
{
return s->root_level;
}
static inline void btrfs_set_super_root_level(struct btrfs_super_block *s,
u8 val)
{
s->root_level = val;
}
static inline u64 btrfs_super_root(struct btrfs_super_block *s)
{
return le64_to_cpu(s->root);
@ -820,26 +833,26 @@ static inline void btrfs_set_super_root(struct btrfs_super_block *s, u64 val)
s->root = cpu_to_le64(val);
}
static inline u64 btrfs_super_total_blocks(struct btrfs_super_block *s)
static inline u64 btrfs_super_total_bytes(struct btrfs_super_block *s)
{
return le64_to_cpu(s->total_blocks);
return le64_to_cpu(s->total_bytes);
}
static inline void btrfs_set_super_total_blocks(struct btrfs_super_block *s,
static inline void btrfs_set_super_total_bytes(struct btrfs_super_block *s,
u64 val)
{
s->total_blocks = cpu_to_le64(val);
s->total_bytes = cpu_to_le64(val);
}
static inline u64 btrfs_super_blocks_used(struct btrfs_super_block *s)
static inline u64 btrfs_super_bytes_used(struct btrfs_super_block *s)
{
return le64_to_cpu(s->blocks_used);
return le64_to_cpu(s->bytes_used);
}
static inline void btrfs_set_super_blocks_used(struct btrfs_super_block *s,
static inline void btrfs_set_super_bytes_used(struct btrfs_super_block *s,
u64 val)
{
s->blocks_used = cpu_to_le64(val);
s->bytes_used = cpu_to_le64(val);
}
static inline u32 btrfs_super_sectorsize(struct btrfs_super_block *s)
@ -904,32 +917,32 @@ static inline void btrfs_set_file_extent_type(struct btrfs_file_extent_item *e,
static inline char *btrfs_file_extent_inline_start(struct
btrfs_file_extent_item *e)
{
return (char *)(&e->disk_blocknr);
return (char *)(&e->disk_bytenr);
}
static inline u32 btrfs_file_extent_calc_inline_size(u32 datasize)
{
return (unsigned long)(&((struct
btrfs_file_extent_item *)NULL)->disk_blocknr) + datasize;
btrfs_file_extent_item *)NULL)->disk_bytenr) + datasize;
}
static inline u32 btrfs_file_extent_inline_len(struct btrfs_item *e)
{
struct btrfs_file_extent_item *fe = NULL;
return btrfs_item_size(e) - (unsigned long)(&fe->disk_blocknr);
return btrfs_item_size(e) - (unsigned long)(&fe->disk_bytenr);
}
static inline u64 btrfs_file_extent_disk_blocknr(struct btrfs_file_extent_item
static inline u64 btrfs_file_extent_disk_bytenr(struct btrfs_file_extent_item
*e)
{
return le64_to_cpu(e->disk_blocknr);
return le64_to_cpu(e->disk_bytenr);
}
static inline void btrfs_set_file_extent_disk_blocknr(struct
static inline void btrfs_set_file_extent_disk_bytenr(struct
btrfs_file_extent_item
*e, u64 val)
{
e->disk_blocknr = cpu_to_le64(val);
e->disk_bytenr = cpu_to_le64(val);
}
static inline u64 btrfs_file_extent_generation(struct btrfs_file_extent_item *e)
@ -944,17 +957,17 @@ static inline void btrfs_set_file_extent_generation(struct
e->generation = cpu_to_le64(val);
}
static inline u64 btrfs_file_extent_disk_num_blocks(struct
static inline u64 btrfs_file_extent_disk_num_bytes(struct
btrfs_file_extent_item *e)
{
return le64_to_cpu(e->disk_num_blocks);
return le64_to_cpu(e->disk_num_bytes);
}
static inline void btrfs_set_file_extent_disk_num_blocks(struct
static inline void btrfs_set_file_extent_disk_num_bytes(struct
btrfs_file_extent_item
*e, u64 val)
{
e->disk_num_blocks = cpu_to_le64(val);
e->disk_num_bytes = cpu_to_le64(val);
}
static inline u64 btrfs_file_extent_offset(struct btrfs_file_extent_item *e)
@ -968,17 +981,17 @@ static inline void btrfs_set_file_extent_offset(struct btrfs_file_extent_item
e->offset = cpu_to_le64(val);
}
static inline u64 btrfs_file_extent_num_blocks(struct btrfs_file_extent_item
static inline u64 btrfs_file_extent_num_bytes(struct btrfs_file_extent_item
*e)
{
return le64_to_cpu(e->num_blocks);
return le64_to_cpu(e->num_bytes);
}
static inline void btrfs_set_file_extent_num_blocks(struct
static inline void btrfs_set_file_extent_num_bytes(struct
btrfs_file_extent_item *e,
u64 val)
{
e->num_blocks = cpu_to_le64(val);
e->num_bytes = cpu_to_le64(val);
}
/* helper function to cast into the data area of the leaf. */
@ -986,15 +999,22 @@ static inline void btrfs_set_file_extent_num_blocks(struct
((type *)(btrfs_leaf_data(leaf) + \
btrfs_item_offset((leaf)->items + (slot))))
static inline u32 btrfs_level_size(struct btrfs_root *root, int level)
{
if (level == 0)
return root->leafsize;
return root->nodesize;
}
int btrfs_comp_keys(struct btrfs_disk_key *disk, struct btrfs_key *k2);
int btrfs_extend_item(struct btrfs_trans_handle *trans, struct btrfs_root
*root, struct btrfs_path *path, u32 data_size);
struct btrfs_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans,
struct btrfs_root *root);
struct btrfs_root *root,
u32 blocksize);
int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
struct btrfs_buffer *buf);
int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
*root, u64 blocknr, u64 num_blocks, int pin);
*root, u64 bytenr, u64 num_bytes, int pin);
int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
*root, struct btrfs_key *key, struct btrfs_path *p, int
ins_len, int cow);

View File

@ -75,7 +75,8 @@ int main(int ac, char **av) {
ri = btrfs_item_ptr(leaf, path.slots[0],
struct btrfs_root_item);
buf = read_tree_block(root->fs_info->tree_root,
btrfs_root_blocknr(ri));
btrfs_root_bytenr(ri),
root->leafsize);
switch(found_key.objectid) {
case BTRFS_ROOT_TREE_OBJECTID:
printf("root ");
@ -93,10 +94,10 @@ int main(int ac, char **av) {
path.slots[0]++;
}
btrfs_release_path(root, &path);
printf("total blocks %llu\n",
(unsigned long long)btrfs_super_total_blocks(&super));
printf("blocks used %llu\n",
(unsigned long long)btrfs_super_blocks_used(&super));
printf("total bytes %llu\n",
(unsigned long long)btrfs_super_total_bytes(&super));
printf("bytes used %llu\n",
(unsigned long long)btrfs_super_bytes_used(&super));
uuidbuf[36] = '\0';
uuid_unparse(super.fsid, uuidbuf);
printf("uuid %s\n", uuidbuf);

114
disk-io.c
View File

@ -31,20 +31,20 @@
#include "transaction.h"
#include "crc32c.h"
static int allocated_blocks = 0;
static u64 allocated_bytes = 0;
int cache_max = 10000;
int btrfs_map_bh_to_logical(struct btrfs_root *root, struct btrfs_buffer *bh,
u64 logical)
{
bh->fd = root->fs_info->fp;
bh->dev_blocknr = logical;
bh->dev_bytenr = logical;
return 0;
}
static int check_tree_block(struct btrfs_root *root, struct btrfs_buffer *buf)
{
if (buf->blocknr != btrfs_header_blocknr(&buf->node.header))
if (buf->bytenr != btrfs_header_bytenr(&buf->node.header))
BUG();
if (memcmp(root->fs_info->disk_super->fsid, buf->node.header.fsid,
sizeof(buf->node.header.fsid)))
@ -71,24 +71,28 @@ static int free_some_buffers(struct btrfs_root *root)
return 0;
}
struct btrfs_buffer *alloc_tree_block(struct btrfs_root *root, u64 blocknr)
struct btrfs_buffer *alloc_tree_block(struct btrfs_root *root, u64 bytenr,
u32 blocksize)
{
struct btrfs_buffer *buf;
int ret;
buf = malloc(sizeof(struct btrfs_buffer) + root->sectorsize);
buf = malloc(sizeof(struct btrfs_buffer) + blocksize);
if (!buf)
return buf;
allocated_blocks++;
buf->blocknr = blocknr;
allocated_bytes += blocksize;
buf->bytenr = bytenr;
buf->count = 2;
buf->size = blocksize;
INIT_LIST_HEAD(&buf->dirty);
free_some_buffers(root);
radix_tree_preload(GFP_KERNEL);
ret = radix_tree_insert(&root->fs_info->cache_radix, blocknr, buf);
ret = radix_tree_insert(&root->fs_info->cache_radix, bytenr, buf);
radix_tree_preload_end();
list_add_tail(&buf->cache, &root->fs_info->cache);
root->fs_info->cache_size++;
root->fs_info->cache_size += blocksize;
if (ret) {
free(buf);
return NULL;
@ -96,14 +100,15 @@ struct btrfs_buffer *alloc_tree_block(struct btrfs_root *root, u64 blocknr)
return buf;
}
struct btrfs_buffer *find_tree_block(struct btrfs_root *root, u64 blocknr)
struct btrfs_buffer *find_tree_block(struct btrfs_root *root, u64 bytenr,
u32 blocksize)
{
struct btrfs_buffer *buf;
buf = radix_tree_lookup(&root->fs_info->cache_radix, blocknr);
buf = radix_tree_lookup(&root->fs_info->cache_radix, bytenr);
if (buf) {
buf->count++;
} else {
buf = alloc_tree_block(root, blocknr);
buf = alloc_tree_block(root, bytenr, blocksize);
if (!buf) {
BUG();
return NULL;
@ -112,23 +117,24 @@ struct btrfs_buffer *find_tree_block(struct btrfs_root *root, u64 blocknr)
return buf;
}
struct btrfs_buffer *read_tree_block(struct btrfs_root *root, u64 blocknr)
struct btrfs_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr,
u32 blocksize)
{
struct btrfs_buffer *buf;
int ret;
buf = radix_tree_lookup(&root->fs_info->cache_radix, blocknr);
buf = radix_tree_lookup(&root->fs_info->cache_radix, bytenr);
if (buf) {
buf->count++;
if (check_tree_block(root, buf))
BUG();
} else {
buf = alloc_tree_block(root, blocknr);
buf = alloc_tree_block(root, bytenr, blocksize);
if (!buf)
return NULL;
btrfs_map_bh_to_logical(root, buf, blocknr);
ret = pread(buf->fd, &buf->node, root->sectorsize,
buf->dev_blocknr * root->sectorsize);
if (ret != root->sectorsize) {
btrfs_map_bh_to_logical(root, buf, bytenr);
ret = pread(buf->fd, &buf->node, blocksize,
buf->dev_bytenr);
if (ret != blocksize) {
free(buf);
return NULL;
}
@ -163,7 +169,8 @@ int clean_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root,
int btrfs_csum_node(struct btrfs_root *root, struct btrfs_node *node)
{
u32 crc;
size_t len = root->sectorsize - BTRFS_CSUM_SIZE;
size_t len = btrfs_level_size(root, btrfs_header_level(&node->header)) -
BTRFS_CSUM_SIZE;
crc = crc32c(0, (char *)(node) + BTRFS_CSUM_SIZE, len);
memcpy(node->header.csum, &crc, BTRFS_CRC32_SIZE);
@ -189,17 +196,17 @@ int write_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root,
{
int ret;
if (buf->blocknr != btrfs_header_blocknr(&buf->node.header))
if (buf->bytenr != btrfs_header_bytenr(&buf->node.header))
BUG();
btrfs_map_bh_to_logical(root, buf, buf->blocknr);
btrfs_map_bh_to_logical(root, buf, buf->bytenr);
if (check_tree_block(root, buf))
BUG();
btrfs_csum_node(root, &buf->node);
ret = pwrite(buf->fd, &buf->node, root->sectorsize,
buf->dev_blocknr * root->sectorsize);
if (ret != root->sectorsize)
ret = pwrite(buf->fd, &buf->node, buf->size,
buf->dev_bytenr);
if (ret != buf->size)
return ret;
return 0;
}
@ -226,17 +233,19 @@ static int commit_tree_roots(struct btrfs_trans_handle *trans,
struct btrfs_fs_info *fs_info)
{
int ret;
u64 old_extent_block;
u64 old_extent_bytenr;
struct btrfs_root *tree_root = fs_info->tree_root;
struct btrfs_root *extent_root = fs_info->extent_root;
btrfs_write_dirty_block_groups(trans, fs_info->extent_root);
while(1) {
old_extent_block = btrfs_root_blocknr(&extent_root->root_item);
if (old_extent_block == extent_root->node->blocknr)
old_extent_bytenr = btrfs_root_bytenr(&extent_root->root_item);
if (old_extent_bytenr == extent_root->node->bytenr)
break;
btrfs_set_root_blocknr(&extent_root->root_item,
extent_root->node->blocknr);
btrfs_set_root_bytenr(&extent_root->root_item,
extent_root->node->bytenr);
extent_root->root_item.level =
btrfs_header_level(&extent_root->node->node.header);
ret = btrfs_update_root(trans, tree_root,
&extent_root->root_key,
&extent_root->root_item);
@ -259,7 +268,9 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, struct
memcpy(&snap_key, &root->root_key, sizeof(snap_key));
root->root_key.offset++;
btrfs_set_root_blocknr(&root->root_item, root->node->blocknr);
btrfs_set_root_bytenr(&root->root_item, root->node->bytenr);
root->root_item.level =
btrfs_header_level(&root->node->node.header);
ret = btrfs_insert_root(trans, root->fs_info->tree_root,
&root->root_key, &root->root_item);
BUG_ON(ret);
@ -304,6 +315,17 @@ static int __setup_root(struct btrfs_super_block *super,
return 0;
}
struct btrfs_buffer *read_root_block(struct btrfs_root *root, u64 bytenr,
u8 level)
{
struct btrfs_buffer *node;
u32 size = btrfs_level_size(root, level);
node = read_tree_block(root, bytenr, size);
BUG_ON(!node);
return node;
}
static int find_and_setup_root(struct btrfs_super_block *super,
struct btrfs_root *tree_root,
struct btrfs_fs_info *fs_info,
@ -316,9 +338,9 @@ static int find_and_setup_root(struct btrfs_super_block *super,
ret = btrfs_find_last_root(tree_root, objectid,
&root->root_item, &root->root_key);
BUG_ON(ret);
root->node = read_tree_block(root,
btrfs_root_blocknr(&root->root_item));
root->node = read_root_block(root,
btrfs_root_bytenr(&root->root_item),
root->root_item.level);
BUG_ON(!root->node);
return 0;
}
@ -369,7 +391,8 @@ struct btrfs_root *open_ctree_fd(int fp, struct btrfs_super_block *super)
BUG_ON(ret < 0);
__setup_root(super, tree_root, fs_info, BTRFS_ROOT_TREE_OBJECTID, fp);
tree_root->node = read_tree_block(tree_root, btrfs_super_root(super));
tree_root->node = read_root_block(tree_root, btrfs_super_root(super),
btrfs_super_root_level(super));
BUG_ON(!tree_root->node);
ret = find_and_setup_root(super, tree_root, fs_info,
@ -393,7 +416,9 @@ int write_ctree_super(struct btrfs_trans_handle *trans, struct btrfs_root
{
int ret;
btrfs_set_super_root(s, root->fs_info->tree_root->node->blocknr);
btrfs_set_super_root(s, root->fs_info->tree_root->node->bytenr);
btrfs_set_super_root_level(s,
btrfs_header_level(&root->fs_info->tree_root->node->node.header));
btrfs_csum_super(root, s);
ret = pwrite(root->fs_info->fp, s, sizeof(*s),
@ -444,7 +469,8 @@ int close_ctree(struct btrfs_root *root, struct btrfs_super_block *s)
root->fs_info->tree_root->node);
btrfs_block_release(root, root->commit_root);
free(root);
printf("on close %d blocks are allocated\n", allocated_blocks);
printf("on close %llu blocks are allocated\n",
(unsigned long long)allocated_bytes);
return 0;
}
@ -457,15 +483,17 @@ void btrfs_block_release(struct btrfs_root *root, struct btrfs_buffer *buf)
BUG_ON(!list_empty(&buf->cache));
BUG_ON(!list_empty(&buf->dirty));
if (!radix_tree_lookup(&root->fs_info->cache_radix,
buf->blocknr))
buf->bytenr))
BUG();
radix_tree_delete(&root->fs_info->cache_radix, buf->blocknr);
radix_tree_delete(&root->fs_info->cache_radix, buf->bytenr);
BUG_ON(allocated_bytes == 0);
allocated_bytes -= buf->size;
BUG_ON(root->fs_info->cache_size == 0);
root->fs_info->cache_size -= buf->size;
memset(buf, 0, sizeof(*buf));
free(buf);
BUG_ON(allocated_blocks == 0);
allocated_blocks--;
BUG_ON(root->fs_info->cache_size == 0);
root->fs_info->cache_size--;
}
}

View File

@ -21,8 +21,8 @@
#include "list.h"
struct btrfs_buffer {
u64 blocknr;
u64 dev_blocknr;
u64 bytenr;
u64 dev_bytenr;
u32 size;
int count;
int fd;
@ -34,8 +34,10 @@ struct btrfs_buffer {
};
};
struct btrfs_buffer *read_tree_block(struct btrfs_root *root, u64 blocknr);
struct btrfs_buffer *find_tree_block(struct btrfs_root *root, u64 blocknr);
struct btrfs_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr,
u32 blocksize);
struct btrfs_buffer *find_tree_block(struct btrfs_root *root, u64 bytenr,
u32 blocksize);
int write_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root,
struct btrfs_buffer *buf);
int dirty_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root,

View File

@ -30,16 +30,8 @@ static int finish_current_insert(struct btrfs_trans_handle *trans, struct
static int run_pending(struct btrfs_trans_handle *trans, struct btrfs_root
*extent_root);
/*
* pending extents are blocks that we're trying to allocate in the extent
* map while trying to grow the map because of other allocations. To avoid
* recursing, they are tagged in the radix tree and cleaned up after
* other allocations are done. The pending tag is also used in the same
* manner for deletes.
*/
static int inc_block_ref(struct btrfs_trans_handle *trans, struct btrfs_root
*root, u64 blocknr)
*root, u64 bytenr, u32 blocksize)
{
struct btrfs_path path;
int ret;
@ -49,9 +41,9 @@ static int inc_block_ref(struct btrfs_trans_handle *trans, struct btrfs_root
u32 refs;
btrfs_init_path(&path);
key.objectid = blocknr;
key.objectid = bytenr;
btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY);
key.offset = 1;
key.offset = blocksize;
ret = btrfs_search_slot(trans, root->fs_info->extent_root, &key, &path,
0, 1);
if (ret != 0)
@ -70,7 +62,7 @@ static int inc_block_ref(struct btrfs_trans_handle *trans, struct btrfs_root
}
static int lookup_block_ref(struct btrfs_trans_handle *trans, struct btrfs_root
*root, u64 blocknr, u32 *refs)
*root, u64 bytenr, u32 blocksize, u32 *refs)
{
struct btrfs_path path;
int ret;
@ -78,8 +70,8 @@ static int lookup_block_ref(struct btrfs_trans_handle *trans, struct btrfs_root
struct btrfs_leaf *l;
struct btrfs_extent_item *item;
btrfs_init_path(&path);
key.objectid = blocknr;
key.offset = 1;
key.objectid = bytenr;
key.offset = blocksize;
btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY);
ret = btrfs_search_slot(trans, root->fs_info->extent_root, &key, &path,
0, 0);
@ -95,17 +87,18 @@ static int lookup_block_ref(struct btrfs_trans_handle *trans, struct btrfs_root
int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
struct btrfs_buffer *buf)
{
u64 blocknr;
u64 bytenr;
int i;
if (!root->ref_cows)
return 0;
if (btrfs_is_leaf(&buf->node))
return 0;
for (i = 0; i < btrfs_header_nritems(&buf->node.header); i++) {
blocknr = btrfs_node_blockptr(&buf->node, i);
inc_block_ref(trans, root, blocknr);
bytenr = btrfs_node_blockptr(&buf->node, i);
inc_block_ref(trans, root, bytenr, root->nodesize);
}
return 0;
}
@ -171,32 +164,32 @@ int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans,
static int update_block_group(struct btrfs_trans_handle *trans,
struct btrfs_root *root,
u64 blocknr, u64 num, int alloc)
u64 bytenr, u64 num, int alloc)
{
struct btrfs_block_group_cache *cache;
struct btrfs_fs_info *info = root->fs_info;
u64 total = num;
u64 old_val;
u64 block_in_group;
u64 byte_in_group;
int ret;
while(total) {
ret = radix_tree_gang_lookup(&info->block_group_radix,
(void *)&cache, blocknr, 1);
(void *)&cache, bytenr, 1);
if (!ret)
return -1;
radix_tree_tag_set(&info->block_group_radix,
cache->key.objectid + cache->key.offset - 1,
BTRFS_BLOCK_GROUP_DIRTY);
block_in_group = blocknr - cache->key.objectid;
byte_in_group = bytenr - cache->key.objectid;
old_val = btrfs_block_group_used(&cache->item);
if (total > cache->key.offset - block_in_group)
num = cache->key.offset - block_in_group;
if (total > cache->key.offset - byte_in_group)
num = cache->key.offset - byte_in_group;
else
num = total;
total -= num;
blocknr += num;
bytenr += num;
if (alloc)
old_val += num;
else
@ -233,7 +226,6 @@ static int finish_current_insert(struct btrfs_trans_handle *trans, struct
struct btrfs_key ins;
struct btrfs_extent_item extent_item;
int ret;
u64 super_blocks_used, root_blocks_used;
struct btrfs_fs_info *info = extent_root->fs_info;
struct pending_extent *pe;
struct pending_extent *next;
@ -256,13 +248,6 @@ static int finish_current_insert(struct btrfs_trans_handle *trans, struct
free_pending_extent(pe);
pe = next;
super_blocks_used = btrfs_super_blocks_used(info->disk_super);
btrfs_set_super_blocks_used(info->disk_super,
super_blocks_used + 1);
root_blocks_used = btrfs_root_blocks_used(&extent_root->root_item);
btrfs_set_root_blocks_used(&extent_root->root_item,
root_blocks_used + 1);
ret = btrfs_insert_item(trans, extent_root, &ins, &extent_item,
sizeof(extent_item));
if (ret) {
@ -277,7 +262,7 @@ static int finish_current_insert(struct btrfs_trans_handle *trans, struct
* remove an extent from the root, returns 0 on success
*/
static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
*root, u64 blocknr, u64 num_blocks, int pin)
*root, u64 bytenr, u64 num_bytes, int pin)
{
struct btrfs_path path;
struct btrfs_key key;
@ -287,10 +272,9 @@ static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
struct btrfs_extent_item *ei;
u32 refs;
BUG_ON(pin && num_blocks != 1);
key.objectid = blocknr;
key.objectid = bytenr;
btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY);
key.offset = num_blocks;
key.offset = num_bytes;
btrfs_init_path(&path);
ret = btrfs_search_slot(trans, extent_root, &key, &path, -1, 1);
@ -306,27 +290,27 @@ static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
refs = btrfs_extent_refs(ei) - 1;
btrfs_set_extent_refs(ei, refs);
if (refs == 0) {
u64 super_blocks_used, root_blocks_used;
u64 super_bytes_used, root_bytes_used;
if (pin) {
int err;
err = insert_pending_extent(&info->pinned_tree,
blocknr, 1);
bytenr, num_bytes);
BUG_ON(err);
}
super_blocks_used = btrfs_super_blocks_used(info->disk_super);
btrfs_set_super_blocks_used(info->disk_super,
super_blocks_used - num_blocks);
root_blocks_used = btrfs_root_blocks_used(&root->root_item);
btrfs_set_root_blocks_used(&root->root_item,
root_blocks_used - num_blocks);
super_bytes_used = btrfs_super_bytes_used(info->disk_super);
btrfs_set_super_bytes_used(info->disk_super,
super_bytes_used - num_bytes);
root_bytes_used = btrfs_root_bytes_used(&root->root_item);
btrfs_set_root_bytes_used(&root->root_item,
root_bytes_used - num_bytes);
ret = btrfs_del_item(trans, extent_root, &path);
if (!pin && extent_root->fs_info->last_insert.objectid >
blocknr)
extent_root->fs_info->last_insert.objectid = blocknr;
bytenr)
extent_root->fs_info->last_insert.objectid = bytenr;
if (ret)
BUG();
ret = update_block_group(trans, root, blocknr, num_blocks, 0);
ret = update_block_group(trans, root, bytenr, num_bytes, 0);
BUG_ON(ret);
}
btrfs_release_path(extent_root, &path);
@ -350,7 +334,7 @@ static int del_pending_extents(struct btrfs_trans_handle *trans, struct
while(pe) {
remove_pending_extent(del_pending, pe);
ret = __free_extent(trans, extent_root,
pe->start, 1, 1);
pe->start, pe->size, 1);
BUG_ON(ret);
next = next_pending_extent(pe);
if (!next)
@ -373,7 +357,7 @@ static int run_pending(struct btrfs_trans_handle *trans, struct btrfs_root
* remove an extent from the root, returns 0 on success
*/
int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
*root, u64 blocknr, u64 num_blocks, int pin)
*root, u64 bytenr, u64 num_bytes, int pin)
{
struct btrfs_root *extent_root = root->fs_info->extent_root;
int pending_ret;
@ -381,11 +365,11 @@ int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
if (root == extent_root) {
ret = insert_pending_extent(&root->fs_info->del_pending,
blocknr, num_blocks);
bytenr, num_bytes);
BUG_ON(ret);
return 0;
}
ret = __free_extent(trans, root, blocknr, num_blocks, pin);
ret = __free_extent(trans, root, bytenr, num_bytes, pin);
pending_ret = run_pending(trans, root->fs_info->extent_root);
return ret ? ret : pending_ret;
}
@ -399,19 +383,18 @@ int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
* Any available blocks before search_start are skipped.
*/
static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
*orig_root, u64 num_blocks, u64 search_start, u64
search_end, struct btrfs_key *ins)
*orig_root, u64 total_needed, u64 search_start,
u64 search_end, struct btrfs_key *ins)
{
struct btrfs_path path;
struct btrfs_key key;
int ret;
u64 hole_size = 0;
int slot = 0;
u64 last_block = 0;
u64 last_byte = 0;
int start_found;
struct btrfs_leaf *l;
struct btrfs_root * root = orig_root->fs_info->extent_root;
int total_needed = num_blocks;
if (root->fs_info->last_insert.objectid > search_start)
search_start = root->fs_info->last_insert.objectid;
@ -445,8 +428,8 @@ check_failed:
start_found = 1;
goto check_pending;
}
ins->objectid = last_block > search_start ?
last_block : search_start;
ins->objectid = last_byte > search_start ?
last_byte : search_start;
ins->offset = (u64)-1 - ins->objectid;
goto check_pending;
}
@ -455,18 +438,18 @@ check_failed:
goto next;
if (key.objectid >= search_start) {
if (start_found) {
if (last_block < search_start)
last_block = search_start;
hole_size = key.objectid - last_block;
if (last_byte < search_start)
last_byte = search_start;
hole_size = key.objectid - last_byte;
if (hole_size > total_needed) {
ins->objectid = last_block;
ins->objectid = last_byte;
ins->offset = hole_size;
goto check_pending;
}
}
}
start_found = 1;
last_block = key.objectid + key.offset;
last_byte = key.objectid + key.offset;
next:
path.slots[0]++;
}
@ -488,7 +471,7 @@ check_pending:
goto check_failed;
}
root->fs_info->last_insert.objectid = ins->objectid;
ins->offset = num_blocks;
ins->offset = total_needed;
return 0;
error:
btrfs_release_path(root, &path);
@ -501,14 +484,14 @@ error:
*
* returns 0 if everything worked, non-zero otherwise.
*/
static int alloc_extent(struct btrfs_trans_handle *trans, struct btrfs_root
*root, u64 owner, u64 num_blocks,
u64 search_start, u64
search_end, struct btrfs_key *ins)
static int alloc_extent(struct btrfs_trans_handle *trans,
struct btrfs_root *root, u64 owner,
u64 num_bytes, u64 search_start,
u64 search_end, struct btrfs_key *ins)
{
int ret;
int pending_ret;
u64 super_blocks_used, root_blocks_used;
u64 super_bytes_used, root_bytes_used;
struct btrfs_fs_info *info = root->fs_info;
struct btrfs_root *extent_root = info->extent_root;
struct btrfs_extent_item extent_item;
@ -516,23 +499,23 @@ static int alloc_extent(struct btrfs_trans_handle *trans, struct btrfs_root
btrfs_set_extent_refs(&extent_item, 1);
btrfs_set_extent_owner(&extent_item, owner);
ret = find_free_extent(trans, root, num_blocks, search_start,
ret = find_free_extent(trans, root, num_bytes, search_start,
search_end, ins);
if (ret)
return ret;
super_bytes_used = btrfs_super_bytes_used(info->disk_super);
btrfs_set_super_bytes_used(info->disk_super, super_bytes_used +
num_bytes);
root_bytes_used = btrfs_root_bytes_used(&root->root_item);
btrfs_set_root_bytes_used(&root->root_item, root_bytes_used +
num_bytes);
if (root == extent_root) {
ret = insert_pending_extent(&root->fs_info->pending_tree,
ins->objectid, ins->offset);
BUG_ON(ret);
return 0;
}
super_blocks_used = btrfs_super_blocks_used(info->disk_super);
btrfs_set_super_blocks_used(info->disk_super, super_blocks_used +
num_blocks);
root_blocks_used = btrfs_root_blocks_used(&root->root_item);
btrfs_set_root_blocks_used(&root->root_item, root_blocks_used +
num_blocks);
ret = btrfs_insert_item(trans, extent_root, ins, &extent_item,
sizeof(extent_item));
@ -551,23 +534,24 @@ static int alloc_extent(struct btrfs_trans_handle *trans, struct btrfs_root
* returns the tree buffer or NULL.
*/
struct btrfs_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans,
struct btrfs_root *root)
struct btrfs_root *root,
u32 blocksize)
{
struct btrfs_key ins;
int ret;
struct btrfs_buffer *buf;
ret = alloc_extent(trans, root, root->root_key.objectid,
1, 0, (unsigned long)-1, &ins);
blocksize, 0, (unsigned long)-1, &ins);
if (ret) {
BUG();
return NULL;
}
ret = update_block_group(trans, root, ins.objectid, ins.offset, 1);
buf = find_tree_block(root, ins.objectid);
buf = find_tree_block(root, ins.objectid, blocksize);
btrfs_set_header_generation(&buf->node.header,
root->root_key.offset + 1);
btrfs_set_header_blocknr(&buf->node.header, buf->blocknr);
btrfs_set_header_bytenr(&buf->node.header, buf->bytenr);
memcpy(buf->node.header.fsid, root->fs_info->disk_super->fsid,
sizeof(buf->node.header.fsid));
dirty_tree_block(trans, root, buf);
@ -584,12 +568,12 @@ static int walk_down_tree(struct btrfs_trans_handle *trans, struct btrfs_root
{
struct btrfs_buffer *next;
struct btrfs_buffer *cur;
u64 blocknr;
u64 bytenr;
int ret;
u32 refs;
ret = lookup_block_ref(trans, root, path->nodes[*level]->blocknr,
&refs);
ret = lookup_block_ref(trans, root, path->nodes[*level]->bytenr,
btrfs_level_size(root, *level), &refs);
BUG_ON(ret);
if (refs > 1)
goto out;
@ -597,20 +581,22 @@ static int walk_down_tree(struct btrfs_trans_handle *trans, struct btrfs_root
* walk down to the last node level and free all the leaves
*/
while(*level > 0) {
u32 size = btrfs_level_size(root, *level - 1);
cur = path->nodes[*level];
if (path->slots[*level] >=
btrfs_header_nritems(&cur->node.header))
break;
blocknr = btrfs_node_blockptr(&cur->node, path->slots[*level]);
ret = lookup_block_ref(trans, root, blocknr, &refs);
bytenr = btrfs_node_blockptr(&cur->node, path->slots[*level]);
ret = lookup_block_ref(trans, root, bytenr, size, &refs);
if (refs != 1 || *level == 1) {
path->slots[*level]++;
ret = btrfs_free_extent(trans, root, blocknr, 1, 1);
ret = btrfs_free_extent(trans, root, bytenr, size, 1);
BUG_ON(ret);
continue;
}
BUG_ON(ret);
next = read_tree_block(root, blocknr);
next = read_tree_block(root, bytenr, size);
if (path->nodes[*level-1])
btrfs_block_release(root, path->nodes[*level-1]);
path->nodes[*level-1] = next;
@ -618,8 +604,8 @@ static int walk_down_tree(struct btrfs_trans_handle *trans, struct btrfs_root
path->slots[*level] = 0;
}
out:
ret = btrfs_free_extent(trans, root, path->nodes[*level]->blocknr, 1,
1);
ret = btrfs_free_extent(trans, root, path->nodes[*level]->bytenr,
btrfs_level_size(root, *level), 1);
btrfs_block_release(root, path->nodes[*level]);
path->nodes[*level] = NULL;
*level += 1;
@ -647,8 +633,8 @@ static int walk_up_tree(struct btrfs_trans_handle *trans, struct btrfs_root
return 0;
} else {
ret = btrfs_free_extent(trans, root,
path->nodes[*level]->blocknr,
1, 1);
path->nodes[*level]->bytenr,
btrfs_level_size(root, *level), 1);
btrfs_block_release(root, path->nodes[*level]);
path->nodes[*level] = NULL;
*level = i + 1;
@ -732,11 +718,11 @@ int btrfs_read_block_groups(struct btrfs_root *root)
struct btrfs_key key;
struct btrfs_key found_key;
struct btrfs_leaf *leaf;
u64 group_size_blocks = BTRFS_BLOCK_GROUP_SIZE / root->sectorsize;
u64 group_size = BTRFS_BLOCK_GROUP_SIZE;
root = root->fs_info->extent_root;
key.objectid = 0;
key.offset = group_size_blocks;
key.offset = group_size;
btrfs_set_key_type(&key, BTRFS_BLOCK_GROUP_ITEM_KEY);
btrfs_init_path(&path);
@ -766,7 +752,7 @@ int btrfs_read_block_groups(struct btrfs_root *root)
found_key.offset - 1, (void *)cache);
BUG_ON(ret);
if (key.objectid >=
btrfs_super_total_blocks(root->fs_info->disk_super))
btrfs_super_total_bytes(root->fs_info->disk_super))
break;
}
btrfs_release_path(root, &path);

179
mkfs.c
View File

@ -85,55 +85,57 @@ error:
static int make_block_groups(struct btrfs_trans_handle *trans,
struct btrfs_root *root)
{
u64 group_size_blocks;
u64 total_blocks;
u64 group_size;
u64 total_bytes;
u64 cur_start;
int ret;
u64 nr = 0;
struct btrfs_block_group_cache *cache;
root = root->fs_info->extent_root;
/* first we bootstrap the things into cache */
group_size_blocks = BTRFS_BLOCK_GROUP_SIZE / root->sectorsize;
group_size = BTRFS_BLOCK_GROUP_SIZE;
cache = malloc(sizeof(*cache));
cache->key.objectid = 0;
cache->key.offset = group_size_blocks;
cache->key.offset = group_size;
btrfs_set_key_type(&cache->key, BTRFS_BLOCK_GROUP_ITEM_KEY);
memset(&cache->item, 0, sizeof(cache->item));
btrfs_set_block_group_used(&cache->item,
btrfs_super_blocks_used(root->fs_info->disk_super));
btrfs_super_bytes_used(root->fs_info->disk_super));
ret = radix_tree_insert(&root->fs_info->block_group_radix,
group_size_blocks - 1, (void *)cache);
group_size - 1, (void *)cache);
BUG_ON(ret);
total_blocks = btrfs_super_total_blocks(root->fs_info->disk_super);
cur_start = group_size_blocks;
while(cur_start < total_blocks) {
total_bytes = btrfs_super_total_bytes(root->fs_info->disk_super);
cur_start = group_size;
while(cur_start < total_bytes) {
cache = malloc(sizeof(*cache));
cache->key.objectid = cur_start;
cache->key.offset = group_size_blocks;
cache->key.offset = group_size;
btrfs_set_key_type(&cache->key, BTRFS_BLOCK_GROUP_ITEM_KEY);
memset(&cache->item, 0, sizeof(cache->item));
if (nr % 3)
cache->item.flags |= BTRFS_BLOCK_GROUP_DATA;
ret = radix_tree_insert(&root->fs_info->block_group_radix,
cur_start + group_size_blocks - 1,
cur_start + group_size - 1,
(void *)cache);
BUG_ON(ret);
cur_start += group_size_blocks;
cur_start += group_size;
nr++;
}
/* then insert all the items */
cur_start = 0;
while(cur_start < total_blocks) {
while(cur_start < total_bytes) {
cache = radix_tree_lookup(&root->fs_info->block_group_radix,
cur_start + group_size_blocks - 1);
cur_start + group_size - 1);
BUG_ON(!cache);
ret = btrfs_insert_block_group(trans, root, &cache->key,
&cache->item);
BUG_ON(ret);
cur_start += group_size_blocks;
cur_start += group_size;
}
return 0;
}
@ -174,7 +176,8 @@ err:
return ret;
}
int mkfs(int fd, char *pathname, u64 num_blocks, u32 blocksize)
int mkfs(int fd, char *pathname, u64 num_bytes, u32 nodesize, u32 leafsize,
u32 sectorsize)
{
struct btrfs_super_block super;
struct btrfs_leaf *empty_leaf;
@ -185,33 +188,37 @@ int mkfs(int fd, char *pathname, u64 num_blocks, u32 blocksize)
char *block;
int ret;
u32 itemoff;
u32 start_block = BTRFS_SUPER_INFO_OFFSET / blocksize;
u32 start_block = BTRFS_SUPER_INFO_OFFSET;
u32 first_free = BTRFS_SUPER_INFO_OFFSET + sectorsize;
btrfs_set_super_generation(&super, 1);
btrfs_set_super_blocknr(&super, start_block);
btrfs_set_super_root(&super, start_block + 1);
btrfs_set_super_bytenr(&super, start_block);
btrfs_set_super_root_level(&super, 0);
btrfs_set_super_root(&super, first_free);
strcpy((char *)(&super.magic), BTRFS_MAGIC);
printf("blocksize is %d\n", blocksize);
btrfs_set_super_sectorsize(&super, blocksize);
btrfs_set_super_leafsize(&super, blocksize);
btrfs_set_super_nodesize(&super, blocksize);
printf("blocksize is %d\n", leafsize);
btrfs_set_super_sectorsize(&super, sectorsize);
btrfs_set_super_leafsize(&super, leafsize);
btrfs_set_super_nodesize(&super, nodesize);
btrfs_set_super_total_blocks(&super, num_blocks);
btrfs_set_super_blocks_used(&super, start_block + 4);
num_bytes = (num_bytes / sectorsize) * sectorsize;
btrfs_set_super_total_bytes(&super, num_bytes);
btrfs_set_super_bytes_used(&super, start_block + 3 * leafsize +
sectorsize);
uuid_generate(super.fsid);
block = malloc(blocksize);
memset(block, 0, blocksize);
BUG_ON(sizeof(super) > blocksize);
block = malloc(sectorsize);
memset(block, 0, sectorsize);
BUG_ON(sizeof(super) > sectorsize);
memcpy(block, &super, sizeof(super));
ret = pwrite(fd, block, blocksize, BTRFS_SUPER_INFO_OFFSET);
BUG_ON(ret != blocksize);
ret = pwrite(fd, block, sectorsize, BTRFS_SUPER_INFO_OFFSET);
BUG_ON(ret != sectorsize);
/* create the tree of root objects */
empty_leaf = malloc(blocksize);
memset(empty_leaf, 0, blocksize);
btrfs_set_header_blocknr(&empty_leaf->header, start_block + 1);
empty_leaf = malloc(leafsize);
memset(empty_leaf, 0, leafsize);
btrfs_set_header_bytenr(&empty_leaf->header, first_free);
btrfs_set_header_nritems(&empty_leaf->header, 2);
btrfs_set_header_generation(&empty_leaf->header, 0);
btrfs_set_header_owner(&empty_leaf->header, BTRFS_ROOT_TREE_OBJECTID);
@ -234,34 +241,35 @@ printf("blocksize is %d\n", blocksize);
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 + 2);
itemoff = __BTRFS_LEAF_DATA_SIZE(leafsize) - sizeof(root_item);
btrfs_set_root_bytenr(&root_item, first_free + leafsize);
root_item.level = 0;
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_blocks_used(&root_item, 1);
btrfs_set_root_bytenr(&root_item, first_free + leafsize * 2);
btrfs_set_root_bytes_used(&root_item, 1);
itemoff = itemoff - sizeof(root_item);
btrfs_set_item_offset(&item, itemoff);
btrfs_set_disk_key_objectid(&item.key, BTRFS_FS_TREE_OBJECTID);
memcpy(empty_leaf->items + 1, &item, sizeof(item));
memcpy(btrfs_leaf_data(empty_leaf) + itemoff,
&root_item, sizeof(root_item));
ret = pwrite(fd, empty_leaf, blocksize, (start_block + 1) * blocksize);
ret = pwrite(fd, empty_leaf, leafsize, first_free);
/* create the items for the extent tree */
btrfs_set_header_blocknr(&empty_leaf->header, start_block + 2);
btrfs_set_header_bytenr(&empty_leaf->header, first_free + leafsize);
btrfs_set_header_nritems(&empty_leaf->header, 4);
/* item1, reserve blocks 0-16 */
btrfs_set_disk_key_objectid(&item.key, 0);
btrfs_set_disk_key_offset(&item.key, start_block + 1);
btrfs_set_disk_key_offset(&item.key, first_free);
btrfs_set_disk_key_type(&item.key, 0);
btrfs_set_disk_key_type(&item.key, BTRFS_EXTENT_ITEM_KEY);
itemoff = __BTRFS_LEAF_DATA_SIZE(blocksize) -
itemoff = __BTRFS_LEAF_DATA_SIZE(leafsize) -
sizeof(struct btrfs_extent_item);
btrfs_set_item_offset(&item, itemoff);
btrfs_set_item_size(&item, sizeof(struct btrfs_extent_item));
@ -272,8 +280,8 @@ printf("blocksize is %d\n", blocksize);
&extent_item, btrfs_item_size(&item));
/* item2, give block 17 to the root */
btrfs_set_disk_key_objectid(&item.key, start_block + 1);
btrfs_set_disk_key_offset(&item.key, 1);
btrfs_set_disk_key_objectid(&item.key, first_free);
btrfs_set_disk_key_offset(&item.key, leafsize);
itemoff = itemoff - sizeof(struct btrfs_extent_item);
btrfs_set_item_offset(&item, itemoff);
memcpy(empty_leaf->items + 1, &item, sizeof(item));
@ -281,8 +289,8 @@ printf("blocksize is %d\n", blocksize);
&extent_item, btrfs_item_size(&item));
/* item3, give block 18 to the extent root */
btrfs_set_disk_key_objectid(&item.key, start_block + 2);
btrfs_set_disk_key_offset(&item.key, 1);
btrfs_set_disk_key_objectid(&item.key, first_free + leafsize);
btrfs_set_disk_key_offset(&item.key, leafsize);
itemoff = itemoff - sizeof(struct btrfs_extent_item);
btrfs_set_item_offset(&item, itemoff);
memcpy(empty_leaf->items + 2, &item, sizeof(item));
@ -290,22 +298,22 @@ printf("blocksize is %d\n", blocksize);
&extent_item, btrfs_item_size(&item));
/* item4, give block 19 to the FS root */
btrfs_set_disk_key_objectid(&item.key, start_block + 3);
btrfs_set_disk_key_offset(&item.key, 1);
btrfs_set_disk_key_objectid(&item.key, first_free + leafsize * 2);
btrfs_set_disk_key_offset(&item.key, leafsize);
itemoff = itemoff - sizeof(struct btrfs_extent_item);
btrfs_set_item_offset(&item, itemoff);
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);
if (ret != blocksize)
ret = pwrite(fd, empty_leaf, leafsize, first_free + leafsize);
if (ret != leafsize)
return -1;
/* finally create the FS root */
btrfs_set_header_blocknr(&empty_leaf->header, start_block + 3);
btrfs_set_header_bytenr(&empty_leaf->header, first_free + leafsize * 2);
btrfs_set_header_nritems(&empty_leaf->header, 0);
ret = pwrite(fd, empty_leaf, blocksize, (start_block + 3) * blocksize);
if (ret != blocksize)
ret = pwrite(fd, empty_leaf, leafsize, first_free + leafsize * 2);
if (ret != leafsize)
return -1;
return 0;
}
@ -322,7 +330,14 @@ u64 device_size(int fd, struct stat *st)
if (ioctl(fd, BLKGETSIZE64, &size) >= 0) {
return size;
}
return 0; }
return 0;
}
static void print_usage(void)
{
fprintf(stderr, "usage: mkfs.btrfs [ -l leafsize ] [ -n nodesize] dev [ blocks ]\n");
exit(1);
}
int main(int ac, char **av)
{
@ -332,23 +347,50 @@ int main(int ac, char **av)
struct stat st;
int ret;
int i;
char *buf = malloc(8192);
u32 leafsize = 8 * 1024;
u32 sectorsize = 4096;
u32 nodesize = 8 * 1024;
char *buf = malloc(sectorsize);
char *realpath_name;
radix_tree_init();
if (ac >= 2) {
file = av[1];
if (ac == 3) {
block_count = atoi(av[2]);
while(1) {
int c;
c = getopt(ac, av, "l:n:");
if (c < 0)
break;
switch(c) {
case 'l':
leafsize = atol(optarg);
break;
case 'n':
nodesize = atol(optarg);
break;
default:
print_usage();
}
}
if (leafsize < sectorsize || (leafsize & (sectorsize - 1))) {
fprintf(stderr, "Illegal leafsize %u\n", leafsize);
exit(1);
}
if (nodesize < sectorsize || (nodesize & (sectorsize - 1))) {
fprintf(stderr, "Illegal nodesize %u\n", nodesize);
exit(1);
}
ac = ac - optind;
if (ac >= 1) {
file = av[optind];
if (ac == 2) {
block_count = atol(av[optind + 1]);
if (!block_count) {
fprintf(stderr, "error finding block count\n");
exit(1);
}
}
} else {
fprintf(stderr, "usage: mkfs.btrfs file [block count]\n");
exit(1);
print_usage();
}
fd = open(file, O_RDWR);
if (fd < 0) {
@ -366,22 +408,24 @@ int main(int ac, char **av)
fprintf(stderr, "unable to find %s size\n", file);
exit(1);
}
block_count /= 8192;
block_count /= sectorsize;
}
if (block_count < 256) {
fprintf(stderr, "device %s is too small\n", file);
exit(1);
}
memset(buf, 0, 8192);
block_count = block_count * sectorsize;
memset(buf, 0, sectorsize);
for(i = 0; i < 64; i++) {
ret = write(fd, buf, 8192);
if (ret != 8192) {
ret = write(fd, buf, sectorsize);
if (ret != sectorsize) {
fprintf(stderr, "unable to zero fill device\n");
exit(1);
}
}
realpath_name = realpath(file, NULL);
ret = mkfs(fd, realpath_name, block_count, 8192);
ret = mkfs(fd, realpath_name, block_count, nodesize, leafsize,
sectorsize);
if (ret) {
fprintf(stderr, "error during mkfs %d\n", ret);
exit(1);
@ -391,8 +435,9 @@ int main(int ac, char **av)
fprintf(stderr, "failed to setup the root directory\n");
exit(1);
}
printf("fs created on %s blocksize %d blocks %llu\n",
file, 8192, (unsigned long long)block_count);
printf("fs created on %s nodesize %u leafsize %u sectorsize %u bytes %llu\n",
file, nodesize, leafsize, sectorsize,
(unsigned long long)block_count);
return 0;
}

View File

@ -58,7 +58,7 @@ void btrfs_print_leaf(struct btrfs_root *root, struct btrfs_leaf *l)
u32 type;
printf("leaf %llu ptrs %d free space %d generation %llu owner %llu\n",
(unsigned long long)btrfs_header_blocknr(&l->header), nr,
(unsigned long long)btrfs_header_bytenr(&l->header), nr,
btrfs_leaf_free_space(root, l),
(unsigned long long)btrfs_header_generation(&l->header),
(unsigned long long)btrfs_header_owner(&l->header));
@ -93,8 +93,9 @@ void btrfs_print_leaf(struct btrfs_root *root, struct btrfs_leaf *l)
break;
case BTRFS_ROOT_ITEM_KEY:
ri = btrfs_item_ptr(l, i, struct btrfs_root_item);
printf("\t\troot data blocknr %llu dirid %llu refs %u\n",
(unsigned long long)btrfs_root_blocknr(ri),
printf("\t\troot data bytenr %llu level %d dirid %llu refs %u\n",
(unsigned long long)btrfs_root_bytenr(ri),
ri->level,
(unsigned long long)btrfs_root_dirid(ri),
btrfs_root_refs(ri));
if (1 || btrfs_root_refs(ri) == 0) {
@ -128,12 +129,12 @@ void btrfs_print_leaf(struct btrfs_root *root, struct btrfs_leaf *l)
btrfs_file_extent_inline_len(l->items + i));
break;
}
printf("\t\textent data disk block %llu nr %llu\n",
(unsigned long long)btrfs_file_extent_disk_blocknr(fi),
(unsigned long long)btrfs_file_extent_disk_num_blocks(fi));
printf("\t\textent data disk byte %llu nr %llu\n",
(unsigned long long)btrfs_file_extent_disk_bytenr(fi),
(unsigned long long)btrfs_file_extent_disk_num_bytes(fi));
printf("\t\textent data offset %llu nr %llu\n",
(unsigned long long)btrfs_file_extent_offset(fi),
(unsigned long long)btrfs_file_extent_num_blocks(fi));
(unsigned long long)btrfs_file_extent_num_bytes(fi));
break;
case BTRFS_BLOCK_GROUP_ITEM_KEY:
bi = btrfs_item_ptr(l, i,
@ -155,6 +156,7 @@ void btrfs_print_tree(struct btrfs_root *root, struct btrfs_buffer *t)
int i;
u32 nr;
struct btrfs_node *c;
u32 size;
if (!t)
return;
@ -165,24 +167,28 @@ void btrfs_print_tree(struct btrfs_root *root, struct btrfs_buffer *t)
return;
}
printf("node %llu level %d ptrs %d free %u generation %llu owner %llu\n",
(unsigned long long)t->blocknr,
(unsigned long long)t->bytenr,
btrfs_header_level(&c->header), nr,
(u32)BTRFS_NODEPTRS_PER_BLOCK(root) - nr,
(unsigned long long)btrfs_header_generation(&c->header),
(unsigned long long)btrfs_header_owner(&c->header));
fflush(stdout);
size = btrfs_level_size(root, btrfs_header_level(&c->header) - 1);
for (i = 0; i < nr; i++) {
printf("\tkey %d (%llu %x %llu) block %llu\n",
u64 blocknr = btrfs_node_blockptr(c, i);
printf("\tkey %d (%llu %x %llu) block %llu (%llu)\n",
i,
(unsigned long long)c->ptrs[i].key.objectid,
c->ptrs[i].key.type,
(unsigned long long)c->ptrs[i].key.offset,
(unsigned long long)btrfs_node_blockptr(c, i));
(unsigned long long)blocknr,
(unsigned long long)blocknr / size);
fflush(stdout);
}
for (i = 0; i < nr; i++) {
struct btrfs_buffer *next_buf = read_tree_block(root,
btrfs_node_blockptr(c, i));
btrfs_node_blockptr(c, i),
size);
struct btrfs_node *next = &next_buf->node;
if (btrfs_is_leaf(next) &&
btrfs_header_level(&c->header) != 1)