Switch to byte granular allocations
authorChris Mason <chris.mason@oracle.com>
Mon, 15 Oct 2007 20:25:14 +0000 (16:25 -0400)
committerDavid Woodhouse <dwmw2@hera.kernel.org>
Mon, 15 Oct 2007 20:25:14 +0000 (16:25 -0400)
Makefile
btrfsck.c
ctree.c
ctree.h
debug-tree.c
disk-io.c
disk-io.h
extent-tree.c
mkfs.c
print-tree.c

index 25c9493..aca1061 100644 (file)
--- 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
index 83c8252..c5d9dd3 100644 (file)
--- 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 0235f98..1da711a 100644 (file)
--- 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 b37de52..ab2238b 100644 (file)
--- 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);
index 5a85b08..e3530fe 100644 (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);
index 4c467c5..72b97c8 100644 (file)
--- a/disk-io.c
+++ b/disk-io.c
 #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--;
        }
 }
 
index 6c0ba72..4374457 100644 (file)
--- 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,
index 85705dc..38f776e 100644 (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);
diff --git a/mkfs.c b/mkfs.c
index da6722e..057ff40 100644 (file)
--- 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;
 }
 
index e1e0aaa..90d5507 100644 (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)