slot);
}
-struct extent_buffer *read_node_slot(struct btrfs_root *root,
+struct extent_buffer *read_node_slot(struct btrfs_fs_info *fs_info,
struct extent_buffer *parent, int slot)
{
int level = btrfs_header_level(parent);
if (level == 0)
return NULL;
- return read_tree_block(root, btrfs_node_blockptr(parent, slot),
- root->nodesize,
+ return read_tree_block(fs_info, btrfs_node_blockptr(parent, slot),
btrfs_node_ptr_generation(parent, slot));
}
struct extent_buffer *mid;
struct extent_buffer *left = NULL;
struct extent_buffer *parent = NULL;
+ struct btrfs_fs_info *fs_info = root->fs_info;
int ret = 0;
int wret;
int pslot;
return 0;
/* promote the child to a root */
- child = read_node_slot(root, mid, 0);
+ child = read_node_slot(fs_info, mid, 0);
BUG_ON(!extent_buffer_uptodate(child));
ret = btrfs_cow_block(trans, root, child, mid, 0, &child);
BUG_ON(ret);
add_root_to_dirty_list(root);
path->nodes[level] = NULL;
clean_tree_block(trans, root, mid);
- wait_on_tree_block_writeback(root, mid);
/* once for the path */
free_extent_buffer(mid);
BTRFS_NODEPTRS_PER_BLOCK(root) / 4)
return 0;
- left = read_node_slot(root, parent, pslot - 1);
+ left = read_node_slot(fs_info, parent, pslot - 1);
if (extent_buffer_uptodate(left)) {
wret = btrfs_cow_block(trans, root, left,
parent, pslot - 1, &left);
goto enospc;
}
}
- right = read_node_slot(root, parent, pslot + 1);
+ right = read_node_slot(fs_info, parent, pslot + 1);
if (extent_buffer_uptodate(right)) {
wret = btrfs_cow_block(trans, root, right,
parent, pslot + 1, &right);
u32 blocksize = right->len;
clean_tree_block(trans, root, right);
- wait_on_tree_block_writeback(root, right);
free_extent_buffer(right);
right = NULL;
- wret = btrfs_del_ptr(trans, root, path,
- level + 1, pslot + 1);
+ wret = btrfs_del_ptr(root, path, level + 1, pslot + 1);
if (wret)
ret = wret;
wret = btrfs_free_extent(trans, root, bytenr,
u64 bytenr = mid->start;
u32 blocksize = mid->len;
clean_tree_block(trans, root, mid);
- wait_on_tree_block_writeback(root, mid);
free_extent_buffer(mid);
mid = NULL;
- wret = btrfs_del_ptr(trans, root, path, level + 1, pslot);
+ wret = btrfs_del_ptr(root, path, level + 1, pslot);
if (wret)
ret = wret;
wret = btrfs_free_extent(trans, root, bytenr, blocksize,
struct extent_buffer *mid;
struct extent_buffer *left = NULL;
struct extent_buffer *parent = NULL;
+ struct btrfs_fs_info *fs_info = root->fs_info;
int ret = 0;
int wret;
int pslot;
if (!parent)
return 1;
- left = read_node_slot(root, parent, pslot - 1);
+ left = read_node_slot(fs_info, parent, pslot - 1);
/* first, try to make some room in the middle buffer */
if (extent_buffer_uptodate(left)) {
}
free_extent_buffer(left);
}
- right= read_node_slot(root, parent, pslot + 1);
+ right= read_node_slot(fs_info, parent, pslot + 1);
/*
* then try to empty the right most buffer into the middle
void reada_for_search(struct btrfs_root *root, struct btrfs_path *path,
int level, int slot, u64 objectid)
{
+ struct btrfs_fs_info *fs_info = root->fs_info;
struct extent_buffer *node;
struct btrfs_disk_key disk_key;
u32 nritems;
int direction = path->reada;
struct extent_buffer *eb;
u32 nr;
- u32 blocksize;
u32 nscan = 0;
if (level != 1)
node = path->nodes[level];
search = btrfs_node_blockptr(node, slot);
- blocksize = root->nodesize;
- eb = btrfs_find_tree_block(root, search, blocksize);
+ eb = btrfs_find_tree_block(fs_info, search, fs_info->nodesize);
if (eb) {
free_extent_buffer(eb);
return;
if ((search >= lowest_read && search <= highest_read) ||
(search < lowest_read && lowest_read - search <= 32768) ||
(search > highest_read && search - highest_read <= 32768)) {
- readahead_tree_block(root, search, blocksize,
+ readahead_tree_block(fs_info, search,
btrfs_node_ptr_generation(node, nr));
- nread += blocksize;
+ nread += fs_info->nodesize;
}
nscan++;
if (path->reada < 2 && (nread > SZ_256K || nscan > 32))
int ret;
int level;
int should_reada = p->reada;
+ struct btrfs_fs_info *fs_info = root->fs_info;
u8 lowest_level = 0;
lowest_level = p->lowest_level;
reada_for_search(root, p, level, slot,
key->objectid);
- b = read_node_slot(root, b, slot);
+ b = read_node_slot(fs_info, b, slot);
if (!extent_buffer_uptodate(b))
return -EIO;
} else {
else
btrfs_node_key(lower, &lower_key, 0);
- c = btrfs_alloc_free_block(trans, root, root->nodesize,
+ c = btrfs_alloc_free_block(trans, root, root->fs_info->nodesize,
root->root_key.objectid, &lower_key,
level, root->node->start, 0);
BUG();
if (nritems == BTRFS_NODEPTRS_PER_BLOCK(root))
BUG();
- if (slot != nritems) {
+ if (slot < nritems) {
+ /* shift the items */
memmove_extent_buffer(lower,
btrfs_node_key_ptr_offset(slot + 1),
btrfs_node_key_ptr_offset(slot),
mid = (c_nritems + 1) / 2;
btrfs_node_key(c, &disk_key, mid);
- split = btrfs_alloc_free_block(trans, root, root->nodesize,
+ split = btrfs_alloc_free_block(trans, root, root->fs_info->nodesize,
root->root_key.objectid,
&disk_key, level, c->start, 0);
if (IS_ERR(split))
struct extent_buffer *right;
struct extent_buffer *upper;
struct btrfs_disk_key disk_key;
+ struct btrfs_fs_info *fs_info = root->fs_info;
int slot;
u32 i;
int free_space;
if (slot >= btrfs_header_nritems(upper) - 1)
return 1;
- right = read_node_slot(root, upper, slot + 1);
+ right = read_node_slot(fs_info, upper, slot + 1);
if (!extent_buffer_uptodate(right)) {
if (IS_ERR(right))
return PTR_ERR(right);
struct btrfs_disk_key disk_key;
struct extent_buffer *right = path->nodes[0];
struct extent_buffer *left;
+ struct btrfs_fs_info *fs_info = root->fs_info;
int slot;
int i;
int free_space;
return 1;
}
- left = read_node_slot(root, path->nodes[1], slot - 1);
+ left = read_node_slot(fs_info, path->nodes[1], slot - 1);
free_space = btrfs_leaf_free_space(root, left);
if (free_space < data_size) {
free_extent_buffer(left);
else
btrfs_item_key(l, &disk_key, mid);
- right = btrfs_alloc_free_block(trans, root, root->nodesize,
+ right = btrfs_alloc_free_block(trans, root, root->fs_info->nodesize,
root->root_key.objectid,
&disk_key, 0, l->start, 0);
if (IS_ERR(right)) {
nritems = btrfs_header_nritems(leaf);
- if (slot != nritems) {
+ if (slot < nritems) {
/* shift the items */
memmove_extent_buffer(leaf, btrfs_item_nr_offset(slot + 1),
btrfs_item_nr_offset(slot),
return ret;
}
-int btrfs_extend_item(struct btrfs_trans_handle *trans,
- struct btrfs_root *root, struct btrfs_path *path,
+int btrfs_extend_item(struct btrfs_root *root, struct btrfs_path *path,
u32 data_size)
{
int ret = 0;
slot = path->slots[0];
BUG_ON(slot < 0);
- if (slot != nritems) {
+ if (slot < nritems) {
unsigned int old_data = btrfs_item_end_nr(leaf, slot);
if (old_data < data_end) {
* continuing all the way the root if required. The root is converted into
* a leaf if all the nodes are emptied.
*/
-int btrfs_del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root,
- struct btrfs_path *path, int level, int slot)
+int btrfs_del_ptr(struct btrfs_root *root, struct btrfs_path *path,
+ int level, int slot)
{
struct extent_buffer *parent = path->nodes[level];
u32 nritems;
int ret = 0;
nritems = btrfs_header_nritems(parent);
- if (slot != nritems -1) {
+ if (slot < nritems - 1) {
+ /* shift the items */
memmove_extent_buffer(parent,
btrfs_node_key_ptr_offset(slot),
btrfs_node_key_ptr_offset(slot + 1),
int ret;
WARN_ON(btrfs_header_generation(leaf) != trans->transid);
- ret = btrfs_del_ptr(trans, root, path, 1, path->slots[1]);
+ ret = btrfs_del_ptr(root, path, 1, path->slots[1]);
if (ret)
return ret;
btrfs_set_header_level(leaf, 0);
} else {
clean_tree_block(trans, root, leaf);
- wait_on_tree_block_writeback(root, leaf);
-
wret = btrfs_del_leaf(trans, root, path, leaf);
BUG_ON(ret);
if (wret)
if (btrfs_header_nritems(leaf) == 0) {
clean_tree_block(trans, root, leaf);
- wait_on_tree_block_writeback(root, leaf);
-
path->slots[1] = slot;
ret = btrfs_del_leaf(trans, root, path, leaf);
BUG_ON(ret);
int level = 1;
struct extent_buffer *c;
struct extent_buffer *next = NULL;
+ struct btrfs_fs_info *fs_info = root->fs_info;
while(level < BTRFS_MAX_LEVEL) {
if (!path->nodes[level])
}
slot--;
- next = read_node_slot(root, c, slot);
+ next = read_node_slot(fs_info, c, slot);
if (!extent_buffer_uptodate(next)) {
if (IS_ERR(next))
return PTR_ERR(next);
path->slots[level] = slot;
if (!level)
break;
- next = read_node_slot(root, next, slot);
+ next = read_node_slot(fs_info, next, slot);
if (!extent_buffer_uptodate(next)) {
if (IS_ERR(next))
return PTR_ERR(next);
int level = 1;
struct extent_buffer *c;
struct extent_buffer *next = NULL;
+ struct btrfs_fs_info *fs_info = root->fs_info;
while(level < BTRFS_MAX_LEVEL) {
if (!path->nodes[level])
if (path->reada)
reada_for_search(root, path, level, slot, 0);
- next = read_node_slot(root, c, slot);
+ next = read_node_slot(fs_info, c, slot);
if (!extent_buffer_uptodate(next))
return -EIO;
break;
break;
if (path->reada)
reada_for_search(root, path, level, 0, 0);
- next = read_node_slot(root, next, 0);
+ next = read_node_slot(fs_info, next, 0);
if (!extent_buffer_uptodate(next))
return -EIO;
}