summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2007-10-15 16:14:19 -0400
committerChris Mason <chris.mason@oracle.com>2008-09-25 11:03:56 -0400
commit5f39d397dfbe140a14edecd4e73c34ce23c4f9ee (patch)
tree280561e4b68d573590557dd27df656869eed8023
parent50b78c24d594e6985f36a9a8d8e2fb74e1664e90 (diff)
Btrfs: Create extent_buffer interface for large blocksizes
Signed-off-by: Chris Mason <chris.mason@oracle.com>
-rw-r--r--fs/btrfs/Makefile2
-rw-r--r--fs/btrfs/ctree.c1484
-rw-r--r--fs/btrfs/ctree.h849
-rw-r--r--fs/btrfs/dir-item.c102
-rw-r--r--fs/btrfs/disk-io.c391
-rw-r--r--fs/btrfs/disk-io.h55
-rw-r--r--fs/btrfs/extent-tree.c294
-rw-r--r--fs/btrfs/extent_map.c672
-rw-r--r--fs/btrfs/extent_map.h75
-rw-r--r--fs/btrfs/file-item.c63
-rw-r--r--fs/btrfs/file.c129
-rw-r--r--fs/btrfs/inode-item.c22
-rw-r--r--fs/btrfs/inode-map.c17
-rw-r--r--fs/btrfs/inode.c435
-rw-r--r--fs/btrfs/print-tree.c96
-rw-r--r--fs/btrfs/print-tree.h4
-rw-r--r--fs/btrfs/root-tree.c51
-rw-r--r--fs/btrfs/super.c7
-rw-r--r--fs/btrfs/sysfs.c10
-rw-r--r--fs/btrfs/transaction.c61
-rw-r--r--fs/btrfs/transaction.h5
-rw-r--r--fs/btrfs/tree-defrag.c58
22 files changed, 2794 insertions, 2088 deletions
diff --git a/fs/btrfs/Makefile b/fs/btrfs/Makefile
index 6341cf7a9f91..a3b51085d7f0 100644
--- a/fs/btrfs/Makefile
+++ b/fs/btrfs/Makefile
@@ -23,4 +23,6 @@ modules_install:
clean:
$(MAKE) -C $(KERNELDIR) M=`pwd` clean
+tester:
+ $(MAKE) -C $(KERNELDIR) M=`pwd` tree-defrag.o transaction.o sysfs.o super.o root-tree.o inode-map.o inode-item.o inode.o file-item.o file.o extent_map.o disk-io.o ctree.o dir-item.o extent-tree.o
endif
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index b41f48ade419..f60920e8a0e0 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -16,21 +16,24 @@
* Boston, MA 021110-1307, USA.
*/
+#include <linux/highmem.h>
#include "ctree.h"
#include "disk-io.h"
#include "transaction.h"
+#include "print-tree.h"
static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root
*root, struct btrfs_path *path, int level);
static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root
*root, struct btrfs_key *ins_key,
struct btrfs_path *path, int data_size);
-static int push_node_left(struct btrfs_trans_handle *trans, struct btrfs_root
- *root, struct buffer_head *dst, struct buffer_head
- *src);
-static int balance_node_right(struct btrfs_trans_handle *trans, struct
- btrfs_root *root, struct buffer_head *dst_buf,
- struct buffer_head *src_buf);
+static int push_node_left(struct btrfs_trans_handle *trans,
+ struct btrfs_root *root, struct extent_buffer *dst,
+ struct extent_buffer *src);
+static int balance_node_right(struct btrfs_trans_handle *trans,
+ struct btrfs_root *root,
+ struct extent_buffer *dst_buf,
+ struct extent_buffer *src_buf);
static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root,
struct btrfs_path *path, int level, int slot);
@@ -62,40 +65,38 @@ void btrfs_release_path(struct btrfs_root *root, struct btrfs_path *p)
for (i = 0; i < BTRFS_MAX_LEVEL; i++) {
if (!p->nodes[i])
break;
- btrfs_block_release(root, p->nodes[i]);
+ free_extent_buffer(p->nodes[i]);
}
memset(p, 0, sizeof(*p));
}
-static int __btrfs_cow_block(struct btrfs_trans_handle *trans, struct btrfs_root
- *root, struct buffer_head *buf, struct buffer_head
- *parent, int parent_slot, struct buffer_head
- **cow_ret, u64 search_start, u64 empty_size)
+static int __btrfs_cow_block(struct btrfs_trans_handle *trans,
+ struct btrfs_root *root,
+ struct extent_buffer *buf,
+ struct extent_buffer *parent, int parent_slot,
+ struct extent_buffer **cow_ret,
+ u64 search_start, u64 empty_size)
{
- struct buffer_head *cow;
- struct btrfs_node *cow_node;
+ struct extent_buffer *cow;
int ret = 0;
int different_trans = 0;
WARN_ON(root->ref_cows && trans->transid != root->last_trans);
- WARN_ON(!buffer_uptodate(buf));
+
cow = btrfs_alloc_free_block(trans, root, search_start, empty_size);
if (IS_ERR(cow))
return PTR_ERR(cow);
- cow_node = btrfs_buffer_node(cow);
- if (buf->b_size != root->blocksize || cow->b_size != root->blocksize)
+ if (buf->len != root->sectorsize || cow->len != root->sectorsize)
WARN_ON(1);
- memcpy(cow_node, btrfs_buffer_node(buf), root->blocksize);
- btrfs_set_header_blocknr(&cow_node->header, bh_blocknr(cow));
- btrfs_set_header_generation(&cow_node->header, trans->transid);
- btrfs_set_header_owner(&cow_node->header, root->root_key.objectid);
+ copy_extent_buffer(cow, buf, 0, 0, cow->len);
+ btrfs_set_header_blocknr(cow, extent_buffer_blocknr(cow));
+ btrfs_set_header_generation(cow, trans->transid);
+ btrfs_set_header_owner(cow, root->root_key.objectid);
- WARN_ON(btrfs_header_generation(btrfs_buffer_header(buf)) >
- trans->transid);
- if (btrfs_header_generation(btrfs_buffer_header(buf)) !=
- trans->transid) {
+ WARN_ON(btrfs_header_generation(buf) > trans->transid);
+ if (btrfs_header_generation(buf) != trans->transid) {
different_trans = 1;
ret = btrfs_inc_ref(trans, root, buf);
if (ret)
@@ -106,29 +107,29 @@ static int __btrfs_cow_block(struct btrfs_trans_handle *trans, struct btrfs_root
if (buf == root->node) {
root->node = cow;
- get_bh(cow);
+ extent_buffer_get(cow);
if (buf != root->commit_root) {
- btrfs_free_extent(trans, root, bh_blocknr(buf), 1, 1);
+ btrfs_free_extent(trans, root,
+ extent_buffer_blocknr(buf), 1, 1);
}
- btrfs_block_release(root, buf);
+ free_extent_buffer(buf);
} else {
- btrfs_set_node_blockptr(btrfs_buffer_node(parent), parent_slot,
- bh_blocknr(cow));
+ btrfs_set_node_blockptr(parent, parent_slot,
+ extent_buffer_blocknr(cow));
btrfs_mark_buffer_dirty(parent);
- WARN_ON(btrfs_header_generation(btrfs_buffer_header(parent)) !=
- trans->transid);
- btrfs_free_extent(trans, root, bh_blocknr(buf), 1, 1);
+ WARN_ON(btrfs_header_generation(parent) != trans->transid);
+ btrfs_free_extent(trans, root, extent_buffer_blocknr(buf),1,1);
}
- btrfs_block_release(root, buf);
+ free_extent_buffer(buf);
btrfs_mark_buffer_dirty(cow);
*cow_ret = cow;
return 0;
}
-int btrfs_cow_block(struct btrfs_trans_handle *trans, struct btrfs_root
- *root, struct buffer_head *buf, struct buffer_head
- *parent, int parent_slot, struct buffer_head
- **cow_ret)
+int btrfs_cow_block(struct btrfs_trans_handle *trans,
+ struct btrfs_root *root, struct extent_buffer *buf,
+ struct extent_buffer *parent, int parent_slot,
+ struct extent_buffer **cow_ret)
{
u64 search_start;
if (trans->transaction != root->fs_info->running_transaction) {
@@ -141,13 +142,12 @@ int btrfs_cow_block(struct btrfs_trans_handle *trans, struct btrfs_root
root->fs_info->generation);
WARN_ON(1);
}
- if (btrfs_header_generation(btrfs_buffer_header(buf)) ==
- trans->transid) {
+ if (btrfs_header_generation(buf) == trans->transid) {
*cow_ret = buf;
return 0;
}
- search_start = bh_blocknr(buf) & ~((u64)65535);
+ search_start = extent_buffer_blocknr(buf) & ~((u64)65535);
return __btrfs_cow_block(trans, root, buf, parent,
parent_slot, cow_ret, search_start, 0);
}
@@ -161,9 +161,11 @@ static int close_blocks(u64 blocknr, u64 other)
return 0;
}
-static int should_defrag_leaf(struct buffer_head *bh)
+#if 0
+static int should_defrag_leaf(struct extent_buffer *eb)
{
- struct btrfs_leaf *leaf = btrfs_buffer_leaf(bh);
+ return 0;
+ struct btrfs_leaf *leaf = btrfs_buffer_leaf(eb);
struct btrfs_disk_key *key;
u32 nritems;
@@ -188,14 +190,17 @@ static int should_defrag_leaf(struct buffer_head *bh)
}
return 0;
}
+#endif
int btrfs_realloc_node(struct btrfs_trans_handle *trans,
- struct btrfs_root *root, struct buffer_head *parent,
+ struct btrfs_root *root, struct extent_buffer *parent,
int cache_only, u64 *last_ret)
{
+ return 0;
+#if 0
struct btrfs_node *parent_node;
- struct buffer_head *cur_bh;
- struct buffer_head *tmp_bh;
+ struct extent_buffer *cur_eb;
+ struct extent_buffer *tmp_eb;
u64 blocknr;
u64 search_start = *last_ret;
u64 last_block = 0;
@@ -281,6 +286,7 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans,
brelse(tmp_bh);
}
return err;
+#endif
}
/*
@@ -289,12 +295,12 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans,
* which is the stop of the leaf data stack
*/
static inline unsigned int leaf_data_end(struct btrfs_root *root,
- struct btrfs_leaf *leaf)
+ struct extent_buffer *leaf)
{
- u32 nr = btrfs_header_nritems(&leaf->header);
+ u32 nr = btrfs_header_nritems(leaf);
if (nr == 0)
return BTRFS_LEAF_DATA_SIZE(root);
- return btrfs_item_offset(leaf->items + nr - 1);
+ return btrfs_item_offset_nr(leaf, nr - 1);
}
/*
@@ -310,9 +316,9 @@ static int comp_keys(struct btrfs_disk_key *disk, struct btrfs_key *k2)
return 1;
if (k1.objectid < k2->objectid)
return -1;
- if (k1.flags > k2->flags)
+ if (k1.type > k2->type)
return 1;
- if (k1.flags < k2->flags)
+ if (k1.type < k2->type)
return -1;
if (k1.offset > k2->offset)
return 1;
@@ -324,37 +330,39 @@ static int comp_keys(struct btrfs_disk_key *disk, struct btrfs_key *k2)
static int check_node(struct btrfs_root *root, struct btrfs_path *path,
int level)
{
- struct btrfs_node *parent = NULL;
- struct btrfs_node *node = btrfs_buffer_node(path->nodes[level]);
+ struct extent_buffer *parent = NULL;
+ struct extent_buffer *node = path->nodes[level];
+ struct btrfs_disk_key parent_key;
+ struct btrfs_disk_key node_key;
int parent_slot;
int slot;
struct btrfs_key cpukey;
- u32 nritems = btrfs_header_nritems(&node->header);
+ u32 nritems = btrfs_header_nritems(node);
if (path->nodes[level + 1])
- parent = btrfs_buffer_node(path->nodes[level + 1]);
+ parent = path->nodes[level + 1];
slot = path->slots[level];
- BUG_ON(!buffer_uptodate(path->nodes[level]));
BUG_ON(nritems == 0);
if (parent) {
- struct btrfs_disk_key *parent_key;
-
parent_slot = path->slots[level + 1];
- parent_key = &parent->ptrs[parent_slot].key;
- BUG_ON(memcmp(parent_key, &node->ptrs[0].key,
+ btrfs_node_key(parent, &parent_key, parent_slot);
+ btrfs_node_key(node, &node_key, 0);
+ BUG_ON(memcmp(&parent_key, &node_key,
sizeof(struct btrfs_disk_key)));
BUG_ON(btrfs_node_blockptr(parent, parent_slot) !=
- btrfs_header_blocknr(&node->header));
+ btrfs_header_blocknr(node));
}
BUG_ON(nritems > BTRFS_NODEPTRS_PER_BLOCK(root));
if (slot != 0) {
- btrfs_disk_key_to_cpu(&cpukey, &node->ptrs[slot - 1].key);
- BUG_ON(comp_keys(&node->ptrs[slot].key, &cpukey) <= 0);
+ btrfs_node_key_to_cpu(node, &cpukey, slot - 1);
+ btrfs_node_key(node, &node_key, slot);
+ BUG_ON(comp_keys(&node_key, &cpukey) <= 0);
}
if (slot < nritems - 1) {
- btrfs_disk_key_to_cpu(&cpukey, &node->ptrs[slot + 1].key);
- BUG_ON(comp_keys(&node->ptrs[slot].key, &cpukey) >= 0);
+ btrfs_node_key_to_cpu(node, &cpukey, slot + 1);
+ btrfs_node_key(node, &node_key, slot);
+ BUG_ON(comp_keys(&node_key, &cpukey) >= 0);
}
return 0;
}
@@ -362,83 +370,172 @@ static int check_node(struct btrfs_root *root, struct btrfs_path *path,
static int check_leaf(struct btrfs_root *root, struct btrfs_path *path,
int level)
{
- struct btrfs_leaf *leaf = btrfs_buffer_leaf(path->nodes[level]);
- struct btrfs_node *parent = NULL;
+ struct extent_buffer *leaf = path->nodes[level];
+ struct extent_buffer *parent = NULL;
int parent_slot;
- int slot = path->slots[0];
struct btrfs_key cpukey;
+ struct btrfs_disk_key parent_key;
+ struct btrfs_disk_key leaf_key;
+ int slot = path->slots[0];
- u32 nritems = btrfs_header_nritems(&leaf->header);
+ u32 nritems = btrfs_header_nritems(leaf);
if (path->nodes[level + 1])
- parent = btrfs_buffer_node(path->nodes[level + 1]);
-
- BUG_ON(btrfs_leaf_free_space(root, leaf) < 0);
+ parent = path->nodes[level + 1];
if (nritems == 0)
return 0;
if (parent) {
- struct btrfs_disk_key *parent_key;
-
parent_slot = path->slots[level + 1];
- parent_key = &parent->ptrs[parent_slot].key;
+ btrfs_node_key(parent, &parent_key, parent_slot);
+ btrfs_item_key(leaf, &leaf_key, 0);
- BUG_ON(memcmp(parent_key, &leaf->items[0].key,
+ BUG_ON(memcmp(&parent_key, &leaf_key,
sizeof(struct btrfs_disk_key)));
BUG_ON(btrfs_node_blockptr(parent, parent_slot) !=
- btrfs_header_blocknr(&leaf->header));
+ btrfs_header_blocknr(leaf));
+ }
+#if 0
+ for (i = 0; nritems > 1 && i < nritems - 2; i++) {
+ btrfs_item_key_to_cpu(leaf, &cpukey, i + 1);
+ btrfs_item_key(leaf, &leaf_key, i);
+ if (comp_keys(&leaf_key, &cpukey) >= 0) {
+ btrfs_print_leaf(root, leaf);
+ printk("slot %d offset bad key\n", i);
+ BUG_ON(1);
+ }
+ if (btrfs_item_offset_nr(leaf, i) !=
+ btrfs_item_end_nr(leaf, i + 1)) {
+ btrfs_print_leaf(root, leaf);
+ printk("slot %d offset bad\n", i);
+ BUG_ON(1);
+ }
+ if (i == 0) {
+ if (btrfs_item_offset_nr(leaf, i) +
+ btrfs_item_size_nr(leaf, i) !=
+ BTRFS_LEAF_DATA_SIZE(root)) {
+ btrfs_print_leaf(root, leaf);
+ printk("slot %d first offset bad\n", i);
+ BUG_ON(1);
+ }
+ }
}
- if (slot != 0) {
- btrfs_disk_key_to_cpu(&cpukey, &leaf->items[slot - 1].key);
- BUG_ON(comp_keys(&leaf->items[slot].key, &cpukey) <= 0);
- BUG_ON(btrfs_item_offset(leaf->items + slot - 1) !=
- btrfs_item_end(leaf->items + slot));
+ if (nritems > 0) {
+ if (btrfs_item_size_nr(leaf, nritems - 1) > 4096) {
+ btrfs_print_leaf(root, leaf);
+ printk("slot %d bad size \n", nritems - 1);
+ BUG_ON(1);
+ }
+ }
+#endif
+ if (slot != 0 && slot < nritems - 1) {
+ btrfs_item_key(leaf, &leaf_key, slot);
+ btrfs_item_key_to_cpu(leaf, &cpukey, slot - 1);
+ if (comp_keys(&leaf_key, &cpukey) <= 0) {
+ btrfs_print_leaf(root, leaf);
+ printk("slot %d offset bad key\n", slot);
+ BUG_ON(1);
+ }
+ if (btrfs_item_offset_nr(leaf, slot - 1) !=
+ btrfs_item_end_nr(leaf, slot)) {
+ btrfs_print_leaf(root, leaf);
+ printk("slot %d offset bad\n", slot);
+ BUG_ON(1);
+ }
}
if (slot < nritems - 1) {
- btrfs_disk_key_to_cpu(&cpukey, &leaf->items[slot + 1].key);
- BUG_ON(comp_keys(&leaf->items[slot].key, &cpukey) >= 0);
- BUG_ON(btrfs_item_offset(leaf->items + slot) !=
- btrfs_item_end(leaf->items + slot + 1));
+ btrfs_item_key(leaf, &leaf_key, slot);
+ btrfs_item_key_to_cpu(leaf, &cpukey, slot + 1);
+ BUG_ON(comp_keys(&leaf_key, &cpukey) >= 0);
+ if (btrfs_item_offset_nr(leaf, slot) !=
+ btrfs_item_end_nr(leaf, slot + 1)) {
+ btrfs_print_leaf(root, leaf);
+ printk("slot %d offset bad\n", slot);
+ BUG_ON(1);
+ }
}
- BUG_ON(btrfs_item_offset(leaf->items) +
- btrfs_item_size(leaf->items) != BTRFS_LEAF_DATA_SIZE(root));
+ BUG_ON(btrfs_item_offset_nr(leaf, 0) +
+ btrfs_item_size_nr(leaf, 0) != BTRFS_LEAF_DATA_SIZE(root));
return 0;
}
static int check_block(struct btrfs_root *root, struct btrfs_path *path,
int level)
{
- struct btrfs_node *node = btrfs_buffer_node(path->nodes[level]);
- if (memcmp(node->header.fsid, root->fs_info->disk_super->fsid,
- sizeof(node->header.fsid)))
- BUG();
+ struct extent_buffer *buf = path->nodes[level];
+ char fsid[BTRFS_FSID_SIZE];
+
+ read_extent_buffer(buf, fsid, (unsigned long)btrfs_header_fsid(buf),
+ BTRFS_FSID_SIZE);
+
+ if (memcmp(fsid, root->fs_info->fsid, BTRFS_FSID_SIZE)) {
+ int i = 0;
+ printk("warning bad block %Lu\n", buf->start);
+ if (!btrfs_buffer_uptodate(buf)) {
+ WARN_ON(1);
+ }
+ for (i = 0; i < BTRFS_FSID_SIZE; i++) {
+ printk("%x:%x ", root->fs_info->fsid[i], fsid[i]);
+ }
+ printk("\n");
+ // BUG();
+ }
if (level == 0)
return check_leaf(root, path, level);
return check_node(root, path, level);
}
/*
- * search for key in the array p. items p are item_size apart
- * and there are 'max' items in p
+ * search for key in the extent_buffer. The items start at offset p,
+ * and they are item_size apart. There are 'max' items in p.
+ *
* the slot in the array is returned via slot, and it points to
* the place where you would insert key if it is not found in
* the array.
*
* slot may point to max if the key is bigger than all of the keys
*/
-static int generic_bin_search(char *p, int item_size, struct btrfs_key *key,
- int max, int *slot)
+static int generic_bin_search(struct extent_buffer *eb, unsigned long p,
+ int item_size, struct btrfs_key *key,
+ int max, int *slot)
{
int low = 0;
int high = max;
int mid;
int ret;
struct btrfs_disk_key *tmp;
+ struct btrfs_disk_key unaligned;
+ unsigned long offset;
+ char *map_token = NULL;
+ char *kaddr = NULL;
+ unsigned long map_start = 0;
+ unsigned long map_len = 0;
while(low < high) {
mid = (low + high) / 2;
- tmp = (struct btrfs_disk_key *)(p + mid * item_size);
+ offset = p + mid * item_size;
+
+ if (!map_token || offset < map_start ||
+ (offset + sizeof(struct btrfs_disk_key)) >
+ map_start + map_len) {
+ if (map_token)
+ unmap_extent_buffer(eb, map_token, KM_USER0);
+ map_extent_buffer(eb, offset, &map_token, &kaddr,
+ &map_start, &map_len, KM_USER0);
+
+ }
+ if (offset + sizeof(struct btrfs_disk_key) >
+ map_start + map_len) {
+ unmap_extent_buffer(eb, map_token, KM_USER0);
+ read_extent_buffer(eb, &unaligned,
+ offset, sizeof(unaligned));
+ map_token = NULL;
+ tmp = &unaligned;
+ } else {
+ tmp = (struct btrfs_disk_key *)(kaddr + offset -
+ map_start);
+ }
ret = comp_keys(tmp, key);
if (ret < 0)
@@ -447,10 +544,13 @@ static int generic_bin_search(char *p, int item_size, struct btrfs_key *key,
high = mid;
else {
*slot = mid;
+ unmap_extent_buffer(eb, map_token, KM_USER0);
return 0;
}
}
*slot = low;
+ if (map_token)
+ unmap_extent_buffer(eb, map_token, KM_USER0);
return 1;
}
@@ -458,46 +558,42 @@ static int generic_bin_search(char *p, int item_size, struct btrfs_key *key,
* simple bin_search frontend that does the right thing for
* leaves vs nodes
*/
-static int bin_search(struct btrfs_node *c, struct btrfs_key *key, int *slot)
+static int bin_search(struct extent_buffer *eb, struct btrfs_key *key,
+ int level, int *slot)
{
- if (btrfs_is_leaf(c)) {
- struct btrfs_leaf *l = (struct btrfs_leaf *)c;
- return generic_bin_search((void *)l->items,
+ if (level == 0) {
+ return generic_bin_search(eb,
+ offsetof(struct btrfs_leaf, items),
sizeof(struct btrfs_item),
- key, btrfs_header_nritems(&c->header),
+ key, btrfs_header_nritems(eb),
slot);
} else {
- return generic_bin_search((void *)c->ptrs,
+ return generic_bin_search(eb,
+ offsetof(struct btrfs_node, ptrs),
sizeof(struct btrfs_key_ptr),
- key, btrfs_header_nritems(&c->header),
+ key, btrfs_header_nritems(eb),
slot);
}
return -1;
}
-static struct buffer_head *read_node_slot(struct btrfs_root *root,
- struct buffer_head *parent_buf,
- int slot)
+static struct extent_buffer *read_node_slot(struct btrfs_root *root,
+ struct extent_buffer *parent, int slot)
{
- struct btrfs_node *node = btrfs_buffer_node(parent_buf);
if (slot < 0)
return NULL;
- if (slot >= btrfs_header_nritems(&node->header))
+ if (slot >= btrfs_header_nritems(parent))
return NULL;
- return read_tree_block(root, btrfs_node_blockptr(node, slot));
+ return read_tree_block(root, btrfs_node_blockptr(parent, slot));
}
static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root
*root, struct btrfs_path *path, int level)
{
- struct buffer_head *right_buf;
- struct buffer_head *mid_buf;
- struct buffer_head *left_buf;
- struct buffer_head *parent_buf = NULL;
- struct btrfs_node *right = NULL;
- struct btrfs_node *mid;
- struct btrfs_node *left = NULL;
- struct btrfs_node *parent = NULL;
+ struct extent_buffer *right = NULL;
+ struct extent_buffer *mid;
+ struct extent_buffer *left = NULL;
+ struct extent_buffer *parent = NULL;
int ret = 0;
int wret;
int pslot;
@@ -508,60 +604,57 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root
if (level == 0)
return 0;
- mid_buf = path->nodes[level];
- mid = btrfs_buffer_node(mid_buf);
+ mid = path->nodes[level];
orig_ptr = btrfs_node_blockptr(mid, orig_slot);
if (level < BTRFS_MAX_LEVEL - 1)
- parent_buf = path->nodes[level + 1];
+ parent = path->nodes[level + 1];
pslot = path->slots[level + 1];
/*
* deal with the case where there is only one pointer in the root
* by promoting the node below to a root
*/
- if (!parent_buf) {
- struct buffer_head *child;
- u64 blocknr = bh_blocknr(mid_buf);
+ if (!parent) {
+ struct extent_buffer *child;
+ u64 blocknr = extent_buffer_blocknr(mid);
- if (btrfs_header_nritems(&mid->header) != 1)
+ if (btrfs_header_nritems(mid) != 1)
return 0;
/* promote the child to a root */
- child = read_node_slot(root, mid_buf, 0);
+ child = read_node_slot(root, mid, 0);
BUG_ON(!child);
root->node = child;
path->nodes[level] = NULL;
- clean_tree_block(trans, root, mid_buf);
- wait_on_buffer(mid_buf);
+ clean_tree_block(trans, root, mid);
+ wait_on_tree_block_writeback(root, mid);
/* once for the path */
- btrfs_block_release(root, mid_buf);
+ free_extent_buffer(mid);
/* once for the root ptr */
- btrfs_block_release(root, mid_buf);
+ free_extent_buffer(mid);
return btrfs_free_extent(trans, root, blocknr, 1, 1);
}
- parent = btrfs_buffer_node(parent_buf);
-
- if (btrfs_header_nritems(&mid->header) >
+ if (btrfs_header_nritems(mid) >
BTRFS_NODEPTRS_PER_BLOCK(root) / 4)
return 0;
- if (btrfs_header_nritems(&mid->header) < 2)
+ if (btrfs_header_nritems(mid) < 2)
err_on_enospc = 1;
- left_buf = read_node_slot(root, parent_buf, pslot - 1);
- if (left_buf) {
- wret = btrfs_cow_block(trans, root, left_buf,
- parent_buf, pslot - 1, &left_buf);
+ left = read_node_slot(root, parent, pslot - 1);
+ if (left) {
+ wret = btrfs_cow_block(trans, root, left,
+ parent, pslot - 1, &left);
if (wret) {
ret = wret;
goto enospc;
}
}
- right_buf = read_node_slot(root, parent_buf, pslot + 1);
- if (right_buf) {
- wret = btrfs_cow_block(trans, root, right_buf,
- parent_buf, pslot + 1, &right_buf);
+ right = read_node_slot(root, parent, pslot + 1);
+ if (right) {
+ wret = btrfs_cow_block(trans, root, right,
+ parent, pslot + 1, &right);
if (wret) {
ret = wret;
goto enospc;
@@ -569,30 +662,27 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root
}
/* first, try to make some room in the middle buffer */
- if (left_buf) {
- left = btrfs_buffer_node(left_buf);
- orig_slot += btrfs_header_nritems(&left->header);
- wret = push_node_left(trans, root, left_buf, mid_buf);
+ if (left) {
+ orig_slot += btrfs_header_nritems(left);
+ wret = push_node_left(trans, root, left, mid);
if (wret < 0)
ret = wret;
- if (btrfs_header_nritems(&mid->header) < 2)
+ if (btrfs_header_nritems(mid) < 2)
err_on_enospc = 1;
}
/*
* then try to empty the right most buffer into the middle
*/
- if (right_buf) {
- right = btrfs_buffer_node(right_buf);
- wret = push_node_left(trans, root, mid_buf, right_buf);
+ if (right) {
+ wret = push_node_left(trans, root, mid, right);
if (wret < 0 && wret != -ENOSPC)
ret = wret;
- if (btrfs_header_nritems(&right->header) == 0) {
- u64 blocknr = bh_blocknr(right_buf);
- clean_tree_block(trans, root, right_buf);
- wait_on_buffer(right_buf);
- btrfs_block_release(root, right_buf);
- right_buf = NULL;
+ if (btrfs_header_nritems(right) == 0) {
+ u64 blocknr = extent_buffer_blocknr(right);
+ clean_tree_block(trans, root, right);
+ wait_on_tree_block_writeback(root, right);
+ free_extent_buffer(right);
right = NULL;
wret = del_ptr(trans, root, path, level + 1, pslot +
1);
@@ -602,14 +692,13 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root
if (wret)
ret = wret;
} else {
- btrfs_memcpy(root, parent,
- &parent->ptrs[pslot + 1].key,
- &right->ptrs[0].key,
- sizeof(struct btrfs_disk_key));
- btrfs_mark_buffer_dirty(parent_buf);
+ struct btrfs_disk_key right_key;
+ btrfs_node_key(right, &right_key, 0);
+ btrfs_set_node_key(parent, &right_key, pslot + 1);
+ btrfs_mark_buffer_dirty(parent);
}
}
- if (btrfs_header_nritems(&mid->header) == 1) {
+ if (btrfs_header_nritems(mid) == 1) {
/*
* we're not allowed to leave a node with one item in the
* tree during a delete. A deletion from lower in the tree
@@ -619,21 +708,20 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root
* otherwise we would have pulled some pointers from the
* right
*/
- BUG_ON(!left_buf);
- wret = balance_node_right(trans, root, mid_buf, left_buf);
+ BUG_ON(!left);
+ wret = balance_node_right(trans, root, mid, left);
if (wret < 0) {
ret = wret;
goto enospc;
}
BUG_ON(wret == 1);
}
- if (btrfs_header_nritems(&mid->header) == 0) {
+ if (btrfs_header_nritems(mid) == 0) {
/* we've managed to empty the middle node, drop it */
- u64 blocknr = bh_blocknr(mid_buf);
- clean_tree_block(trans, root, mid_buf);
- wait_on_buffer(mid_buf);
- btrfs_block_release(root, mid_buf);
- mid_buf = NULL;
+ u64 blocknr = extent_buffer_blocknr(mid);
+ clean_tree_block(trans, root, mid);
+ wait_on_tree_block_writeback(root, mid);
+ free_extent_buffer(mid);
mid = NULL;
wret = del_ptr(trans, root, path, level + 1, pslot);
if (wret)
@@ -643,37 +731,36 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root
ret = wret;
} else {
/* update the parent key to reflect our changes */
- btrfs_memcpy(root, parent,
- &parent->ptrs[pslot].key, &mid->ptrs[0].key,
- sizeof(struct btrfs_disk_key));
- btrfs_mark_buffer_dirty(parent_buf);
+ struct btrfs_disk_key mid_key;
+ btrfs_node_key(mid, &mid_key, 0);
+ btrfs_set_node_key(parent, &mid_key, pslot);
+ btrfs_mark_buffer_dirty(parent);
}
/* update the path */
- if (left_buf) {
- if (btrfs_header_nritems(&left->header) > orig_slot) {
- get_bh(left_buf);
- path->nodes[level] = left_buf;
+ if (left) {
+ if (btrfs_header_nritems(left) > orig_slot) {
+ extent_buffer_get(left);
+ path->nodes[level] = left;
path->slots[level + 1] -= 1;
path->slots[level] = orig_slot;
- if (mid_buf)
- btrfs_block_release(root, mid_buf);
+ if (mid)
+ free_extent_buffer(mid);
} else {
- orig_slot -= btrfs_header_nritems(&left->header);
+ orig_slot -= btrfs_header_nritems(left);
path->slots[level] = orig_slot;
}
}
/* double check we haven't messed things up */
check_block(root, path, level);
if (orig_ptr !=
- btrfs_node_blockptr(btrfs_buffer_node(path->nodes[level]),
- path->slots[level]))
+ btrfs_node_blockptr(path->nodes[level], path->slots[level]))
BUG();
enospc:
- if (right_buf)
- btrfs_block_release(root, right_buf);
- if (left_buf)
- btrfs_block_release(root, left_buf);
+ if (right)
+ free_extent_buffer(right);
+ if (left)
+ free_extent_buffer(left);
return ret;
}
@@ -682,14 +769,10 @@ static int push_nodes_for_insert(struct btrfs_trans_handle *trans,
struct btrfs_root *root,
struct btrfs_path *path, int level)
{
- struct buffer_head *right_buf;
- struct buffer_head *mid_buf;
- struct buffer_head *left_buf;
- struct buffer_head *parent_buf = NULL;
- struct btrfs_node *right = NULL;
- struct btrfs_node *mid;
- struct btrfs_node *left = NULL;
- struct btrfs_node *parent = NULL;
+ struct extent_buffer *right = NULL;
+ struct extent_buffer *mid;
+ struct extent_buffer *left = NULL;
+ struct extent_buffer *parent = NULL;
int ret = 0;
int wret;
int pslot;
@@ -699,107 +782,101 @@ static int push_nodes_for_insert(struct btrfs_trans_handle *trans,
if (level == 0)
return 1;
- mid_buf = path->nodes[level];
- mid = btrfs_buffer_node(mid_buf);
+ mid = path->nodes[level];
orig_ptr = btrfs_node_blockptr(mid, orig_slot);
if (level < BTRFS_MAX_LEVEL - 1)
- parent_buf = path->nodes[level + 1];
+ parent = path->nodes[level + 1];
pslot = path->slots[level + 1];
- if (!parent_buf)
+ if (!parent)
return 1;
- parent = btrfs_buffer_node(parent_buf);
- left_buf = read_node_slot(root, parent_buf, pslot - 1);
+ left = read_node_slot(root, parent, pslot - 1);
/* first, try to make some room in the middle buffer */
- if (left_buf) {
+ if (left) {
u32 left_nr;
- left = btrfs_buffer_node(left_buf);
- left_nr = btrfs_header_nritems(&left->header);
+ left_nr = btrfs_header_nritems(left);
if (left_nr >= BTRFS_NODEPTRS_PER_BLOCK(root) - 1) {
wret = 1;
} else {
- ret = btrfs_cow_block(trans, root, left_buf, parent_buf,
- pslot - 1, &left_buf);
+ ret = btrfs_cow_block(trans, root, left, parent,
+ pslot - 1, &left);
if (ret)
wret = 1;
else {
- left = btrfs_buffer_node(left_buf);
wret = push_node_left(trans, root,
- left_buf, mid_buf);
+ left, mid);
}
}
if (wret < 0)
ret = wret;
if (wret == 0) {
+ struct btrfs_disk_key disk_key;
orig_slot += left_nr;
- btrfs_memcpy(root, parent,
- &parent->ptrs[pslot].key,
- &mid->ptrs[0].key,
- sizeof(struct btrfs_disk_key));
- btrfs_mark_buffer_dirty(parent_buf);
- if (btrfs_header_nritems(&left->header) > orig_slot) {
- path->nodes[level] = left_buf;
+ btrfs_node_key(mid, &disk_key, 0);
+ btrfs_set_node_key(parent, &disk_key, pslot);
+ btrfs_mark_buffer_dirty(parent);
+ if (btrfs_header_nritems(left) > orig_slot) {
+ path->nodes[level] = left;
path->slots[level + 1] -= 1;
path->slots[level] = orig_slot;
- btrfs_block_release(root, mid_buf);
+ free_extent_buffer(mid);
} else {
orig_slot -=
- btrfs_header_nritems(&left->header);
+ btrfs_header_nritems(left);
path->slots[level] = orig_slot;
- btrfs_block_release(root, left_buf);
+ free_extent_buffer(left);
}
check_node(root, path, level);
return 0;
}
- btrfs_block_release(root, left_buf);
+ free_extent_buffer(left);
}
- right_buf = read_node_slot(root, parent_buf, pslot + 1);
+ right= read_node_slot(root, parent, pslot + 1);
/*
* then try to empty the right most buffer into the middle
*/
- if (right_buf) {
+ if (right) {
u32 right_nr;
- right = btrfs_buffer_node(right_buf);
- right_nr = btrfs_header_nritems(&right->header);
+ right_nr = btrfs_header_nritems(right);
if (right_nr >= BTRFS_NODEPTRS_PER_BLOCK(root) - 1) {
wret = 1;
} else {
- ret = btrfs_cow_block(trans, root, right_buf,
- parent_buf, pslot + 1,
- &right_buf);
+ ret = btrfs_cow_block(trans, root, right,
+ parent, pslot + 1,
+