#include "transaction.h"
#include "print-tree.h"
#include "repair.h"
+#include "internal.h"
static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root
*root, struct btrfs_path *path, int level);
struct extent_buffer *buf)
{
/*
- * Tree blocks not in refernece counted trees and tree roots
+ * Tree blocks not in reference counted trees and tree roots
* are never shared. If a block was allocated after the last
* snapshot and the block was not allocated by tree relocation,
* we know the block is not shared.
return NULL;
return read_tree_block(root, btrfs_node_blockptr(parent, slot),
- btrfs_level_size(root, level - 1),
+ root->nodesize,
btrfs_node_ptr_generation(parent, slot));
}
node = path->nodes[level];
search = btrfs_node_blockptr(node, slot);
- blocksize = btrfs_level_size(root, level - 1);
+ blocksize = root->nodesize;
eb = btrfs_find_tree_block(root, search, blocksize);
if (eb) {
free_extent_buffer(eb);
path = found_path;
ret = btrfs_search_slot(NULL, fs_root, &key, path, 0, 0);
- if ((ret < 0) || (found_key == NULL)) {
- if (path != found_path)
- btrfs_free_path(path);
- return ret;
- }
+ if ((ret < 0) || (found_key == NULL))
+ goto out;
eb = path->nodes[0];
if (ret && path->slots[0] >= btrfs_header_nritems(eb)) {
ret = btrfs_next_leaf(fs_root, path);
if (ret)
- return ret;
+ goto out;
eb = path->nodes[0];
}
btrfs_item_key_to_cpu(eb, found_key, path->slots[0]);
if (found_key->type != key.type ||
- found_key->objectid != key.objectid)
- return 1;
+ found_key->objectid != key.objectid) {
+ ret = 1;
+ goto out;
+ }
- return 0;
+out:
+ if (path != found_path)
+ btrfs_free_path(path);
+ return ret;
}
/*
*/
int btrfs_leaf_free_space(struct btrfs_root *root, struct extent_buffer *leaf)
{
+ u32 nodesize = (root ? BTRFS_LEAF_DATA_SIZE(root) : leaf->len);
int nritems = btrfs_header_nritems(leaf);
int ret;
- ret = BTRFS_LEAF_DATA_SIZE(root) - leaf_space_used(leaf, 0, nritems);
+ ret = nodesize - leaf_space_used(leaf, 0, nritems);
if (ret < 0) {
- printk("leaf free space ret %d, leaf data size %lu, used %d nritems %d\n",
- ret, (unsigned long) BTRFS_LEAF_DATA_SIZE(root),
- leaf_space_used(leaf, 0, nritems), nritems);
+ printk("leaf free space ret %d, leaf data size %u, used %d nritems %d\n",
+ ret, nodesize, leaf_space_used(leaf, 0, nritems),
+ nritems);
}
return ret;
}
else
btrfs_item_key(l, &disk_key, mid);
- right = btrfs_alloc_free_block(trans, root, root->leafsize,
+ right = btrfs_alloc_free_block(trans, root, root->nodesize,
root->root_key.objectid,
&disk_key, 0, l->start, 0);
if (IS_ERR(right)) {
buf = kmalloc(item_size, GFP_NOFS);
+ BUG_ON(!buf);
read_extent_buffer(leaf, buf, btrfs_item_ptr_offset(leaf,
path->slots[0]), item_size);
slot = path->slots[0] + 1;
unsigned long ptr;
path = btrfs_alloc_path();
- BUG_ON(!path);
+ if (!path)
+ return -ENOMEM;
+
ret = btrfs_insert_empty_item(trans, root, path, cpu_key, data_size);
if (!ret) {
leaf = path->nodes[0];
{
struct btrfs_key found_key;
struct extent_buffer *leaf;
+ u32 nritems;
int ret;
while(1) {
path->slots[0]--;
}
leaf = path->nodes[0];
+ nritems = btrfs_header_nritems(leaf);
+ if (nritems == 0)
+ return 1;
+ if (path->slots[0] == nritems)
+ path->slots[0]--;
+
btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
+ if (found_key.objectid < min_objectid)
+ break;
if (found_key.type == type)
return 0;
+ if (found_key.objectid == min_objectid &&
+ found_key.type < type)
+ break;
}
return 1;
}
}
return 1;
}
+
+/*
+ * Search in extent tree to found next meta/data extent
+ * Caller needs to check for no-hole or skinny metadata features.
+ */
+int btrfs_next_extent_item(struct btrfs_root *root,
+ struct btrfs_path *path, u64 max_objectid)
+{
+ struct btrfs_key found_key;
+ int ret;
+
+ while (1) {
+ ret = btrfs_next_item(root, path);
+ if (ret)
+ return ret;
+ btrfs_item_key_to_cpu(path->nodes[0], &found_key,
+ path->slots[0]);
+ if (found_key.objectid > max_objectid)
+ return 1;
+ if (found_key.type == BTRFS_EXTENT_ITEM_KEY ||
+ found_key.type == BTRFS_METADATA_ITEM_KEY)
+ return 0;
+ }
+}