From 38f79f9077fce76eabc5566319f33b8e800fb96d Mon Sep 17 00:00:00 2001 From: Chris Mason Date: Mon, 15 Oct 2007 16:25:14 -0400 Subject: Switch to byte granular allocations --- Makefile | 3 +- btrfsck.c | 6 +- ctree.c | 97 +++++++++++++++++-------------- ctree.h | 122 ++++++++++++++++++++++----------------- debug-tree.c | 11 ++-- disk-io.c | 114 +++++++++++++++++++++++-------------- disk-io.h | 10 ++-- extent-tree.c | 172 ++++++++++++++++++++++++++----------------------------- mkfs.c | 179 ++++++++++++++++++++++++++++++++++++---------------------- print-tree.c | 28 +++++---- 10 files changed, 423 insertions(+), 319 deletions(-) diff --git a/Makefile b/Makefile index 25c94939..aca10613 100644 --- a/Makefile +++ b/Makefile @@ -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 diff --git a/btrfsck.c b/btrfsck.c index 83c8252c..c5d9dd37 100644 --- a/btrfsck.c +++ b/btrfsck.c @@ -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++) { diff --git a/ctree.c b/ctree.c index 0235f98f..1da711ab 100644 --- a/ctree.c +++ b/ctree.c @@ -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; } diff --git a/ctree.h b/ctree.h index b37de525..ab2238b6 100644 --- a/ctree.h +++ b/ctree.h @@ -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); diff --git a/debug-tree.c b/debug-tree.c index 5a85b080..e3530fed 100644 --- a/debug-tree.c +++ b/debug-tree.c @@ -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); diff --git a/disk-io.c b/disk-io.c index 4c467c5c..72b97c8a 100644 --- a/disk-io.c +++ b/disk-io.c @@ -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--; } } diff --git a/disk-io.h b/disk-io.h index 6c0ba722..43744579 100644 --- a/disk-io.h +++ b/disk-io.h @@ -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, diff --git a/extent-tree.c b/extent-tree.c index 85705dca..38f776e4 100644 --- a/extent-tree.c +++ b/extent-tree.c @@ -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); diff --git a/mkfs.c b/mkfs.c index da6722e6..057ff40b 100644 --- a/mkfs.c +++ b/mkfs.c @@ -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; } diff --git a/print-tree.c b/print-tree.c index e1e0aaa4..90d55073 100644 --- a/print-tree.c +++ b/print-tree.c @@ -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) -- cgit v1.2.3