summaryrefslogtreecommitdiff
path: root/ctree.c
diff options
context:
space:
mode:
authorDimitri John Ledkov <xnox@ubuntu.com>2018-05-08 14:17:29 -0700
committerDimitri John Ledkov <xnox@ubuntu.com>2018-05-08 14:17:29 -0700
commitd00c9550da1801a0eaff5cedf4312e24691b31ea (patch)
tree3881ca1764ef792259e1b70f12c884a3ac0c0715 /ctree.c
parentdab6d2181f1f194ec3a76d900cf2c6533379cbea (diff)
New upstream release.
Diffstat (limited to 'ctree.c')
-rw-r--r--ctree.c82
1 files changed, 50 insertions, 32 deletions
diff --git a/ctree.c b/ctree.c
index 45b368ce..d1c41925 100644
--- a/ctree.c
+++ b/ctree.c
@@ -22,6 +22,7 @@
#include "repair.h"
#include "internal.h"
#include "sizes.h"
+#include "messages.h"
static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root
*root, struct btrfs_path *path, int level);
@@ -479,11 +480,11 @@ btrfs_check_leaf(struct btrfs_root *root, struct btrfs_disk_key *parent_key,
(unsigned long long)btrfs_header_bytenr(buf));
goto fail;
}
- if (btrfs_leaf_free_space(root, buf) < 0) {
+ if (btrfs_leaf_free_space(root->fs_info, buf) < 0) {
ret = BTRFS_TREE_BLOCK_INVALID_FREE_SPACE;
fprintf(stderr, "leaf free space incorrect %llu %d\n",
(unsigned long long)btrfs_header_bytenr(buf),
- btrfs_leaf_free_space(root, buf));
+ btrfs_leaf_free_space(root->fs_info, buf));
goto fail;
}
@@ -642,7 +643,9 @@ static int bin_search(struct extent_buffer *eb, struct btrfs_key *key,
struct extent_buffer *read_node_slot(struct btrfs_fs_info *fs_info,
struct extent_buffer *parent, int slot)
{
+ struct extent_buffer *ret;
int level = btrfs_header_level(parent);
+
if (slot < 0)
return NULL;
if (slot >= btrfs_header_nritems(parent))
@@ -651,8 +654,20 @@ struct extent_buffer *read_node_slot(struct btrfs_fs_info *fs_info,
if (level == 0)
return NULL;
- return read_tree_block(fs_info, btrfs_node_blockptr(parent, slot),
+ ret = read_tree_block(fs_info, btrfs_node_blockptr(parent, slot),
btrfs_node_ptr_generation(parent, slot));
+ if (!extent_buffer_uptodate(ret))
+ return ERR_PTR(-EIO);
+
+ if (btrfs_header_level(ret) != level - 1) {
+ error(
+"child eb corrupted: parent bytenr=%llu item=%d parent level=%d child level=%d",
+ btrfs_header_bytenr(parent), slot,
+ btrfs_header_level(parent), btrfs_header_level(ret));
+ free_extent_buffer(ret);
+ return ERR_PTR(-EIO);
+ }
+ return ret;
}
static int balance_level(struct btrfs_trans_handle *trans,
@@ -1178,7 +1193,7 @@ again:
} else {
p->slots[level] = slot;
if (ins_len > 0 &&
- ins_len > btrfs_leaf_free_space(root, b)) {
+ ins_len > btrfs_leaf_free_space(root->fs_info, b)) {
int sret = split_leaf(trans, root, key,
p, ins_len, ret == 0);
BUG_ON(sret > 0);
@@ -1619,16 +1634,17 @@ static int leaf_space_used(struct extent_buffer *l, int start, int nr)
* the start of the leaf data. IOW, how much room
* the leaf has left for both items and data
*/
-int btrfs_leaf_free_space(struct btrfs_root *root, struct extent_buffer *leaf)
+int btrfs_leaf_free_space(struct btrfs_fs_info *fs_info,
+ struct extent_buffer *leaf)
{
- u32 nodesize = (root ? BTRFS_LEAF_DATA_SIZE(root->fs_info) : leaf->len);
int nritems = btrfs_header_nritems(leaf);
int ret;
- ret = nodesize - leaf_space_used(leaf, 0, nritems);
+
+ ret = BTRFS_LEAF_DATA_SIZE(fs_info) - leaf_space_used(leaf, 0, nritems);
if (ret < 0) {
- printk("leaf free space ret %d, leaf data size %u, used %d nritems %d\n",
- ret, nodesize, leaf_space_used(leaf, 0, nritems),
- nritems);
+ printk("leaf free space ret %d, leaf data size %lu, used %d nritems %d\n",
+ ret, BTRFS_LEAF_DATA_SIZE(fs_info),
+ leaf_space_used(leaf, 0, nritems), nritems);
}
return ret;
}
@@ -1676,7 +1692,7 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root
return PTR_ERR(right);
return -EIO;
}
- free_space = btrfs_leaf_free_space(root, right);
+ free_space = btrfs_leaf_free_space(fs_info, right);
if (free_space < data_size) {
free_extent_buffer(right);
return 1;
@@ -1689,7 +1705,7 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root
free_extent_buffer(right);
return 1;
}
- free_space = btrfs_leaf_free_space(root, right);
+ free_space = btrfs_leaf_free_space(fs_info, right);
if (free_space < data_size) {
free_extent_buffer(right);
return 1;
@@ -1828,7 +1844,7 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root
}
left = read_node_slot(fs_info, path->nodes[1], slot - 1);
- free_space = btrfs_leaf_free_space(root, left);
+ free_space = btrfs_leaf_free_space(fs_info, left);
if (free_space < data_size) {
free_extent_buffer(left);
return 1;
@@ -1843,7 +1859,7 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root
return 1;
}
- free_space = btrfs_leaf_free_space(root, left);
+ free_space = btrfs_leaf_free_space(fs_info, left);
if (free_space < data_size) {
free_extent_buffer(left);
return 1;
@@ -2067,7 +2083,7 @@ static noinline int split_leaf(struct btrfs_trans_handle *trans,
l = path->nodes[0];
/* did the pushes work? */
- if (btrfs_leaf_free_space(root, l) >= data_size)
+ if (btrfs_leaf_free_space(root->fs_info, l) >= data_size)
return 0;
}
@@ -2224,7 +2240,8 @@ int btrfs_split_item(struct btrfs_trans_handle *trans,
leaf = path->nodes[0];
btrfs_item_key_to_cpu(leaf, &orig_key, path->slots[0]);
- if (btrfs_leaf_free_space(root, leaf) >= sizeof(struct btrfs_item))
+ if (btrfs_leaf_free_space(root->fs_info, leaf) >=
+ sizeof(struct btrfs_item))
goto split;
item_size = btrfs_item_size_nr(leaf, path->slots[0]);
@@ -2244,7 +2261,8 @@ int btrfs_split_item(struct btrfs_trans_handle *trans,
ret = split_leaf(trans, root, &orig_key, path, 0, 0);
BUG_ON(ret);
- BUG_ON(btrfs_leaf_free_space(root, leaf) < sizeof(struct btrfs_item));
+ BUG_ON(btrfs_leaf_free_space(root->fs_info, leaf) <
+ sizeof(struct btrfs_item));
leaf = path->nodes[0];
split:
@@ -2296,8 +2314,8 @@ split:
btrfs_mark_buffer_dirty(leaf);
ret = 0;
- if (btrfs_leaf_free_space(root, leaf) < 0) {
- btrfs_print_leaf(root, leaf);
+ if (btrfs_leaf_free_space(root->fs_info, leaf) < 0) {
+ btrfs_print_leaf(leaf);
BUG();
}
kfree(buf);
@@ -2392,8 +2410,8 @@ int btrfs_truncate_item(struct btrfs_root *root, struct btrfs_path *path,
btrfs_mark_buffer_dirty(leaf);
ret = 0;
- if (btrfs_leaf_free_space(root, leaf) < 0) {
- btrfs_print_leaf(root, leaf);
+ if (btrfs_leaf_free_space(root->fs_info, leaf) < 0) {
+ btrfs_print_leaf(leaf);
BUG();
}
return ret;
@@ -2417,8 +2435,8 @@ int btrfs_extend_item(struct btrfs_root *root, struct btrfs_path *path,
nritems = btrfs_header_nritems(leaf);
data_end = leaf_data_end(root->fs_info, leaf);
- if (btrfs_leaf_free_space(root, leaf) < data_size) {
- btrfs_print_leaf(root, leaf);
+ if (btrfs_leaf_free_space(root->fs_info, leaf) < data_size) {
+ btrfs_print_leaf(leaf);
BUG();
}
slot = path->slots[0];
@@ -2426,7 +2444,7 @@ int btrfs_extend_item(struct btrfs_root *root, struct btrfs_path *path,
BUG_ON(slot < 0);
if (slot >= nritems) {
- btrfs_print_leaf(root, leaf);
+ btrfs_print_leaf(leaf);
printk("slot %d too large, nritems %d\n", slot, nritems);
BUG_ON(1);
}
@@ -2454,8 +2472,8 @@ int btrfs_extend_item(struct btrfs_root *root, struct btrfs_path *path,
btrfs_mark_buffer_dirty(leaf);
ret = 0;
- if (btrfs_leaf_free_space(root, leaf) < 0) {
- btrfs_print_leaf(root, leaf);
+ if (btrfs_leaf_free_space(root->fs_info, leaf) < 0) {
+ btrfs_print_leaf(leaf);
BUG();
}
return ret;
@@ -2503,10 +2521,10 @@ int btrfs_insert_empty_items(struct btrfs_trans_handle *trans,
nritems = btrfs_header_nritems(leaf);
data_end = leaf_data_end(root->fs_info, leaf);
- if (btrfs_leaf_free_space(root, leaf) < total_size) {
- btrfs_print_leaf(root, leaf);
+ if (btrfs_leaf_free_space(root->fs_info, leaf) < total_size) {
+ btrfs_print_leaf(leaf);
printk("not enough freespace need %u have %d\n",
- total_size, btrfs_leaf_free_space(root, leaf));
+ total_size, btrfs_leaf_free_space(root->fs_info, leaf));
BUG();
}
@@ -2517,7 +2535,7 @@ int btrfs_insert_empty_items(struct btrfs_trans_handle *trans,
unsigned int old_data = btrfs_item_end_nr(leaf, slot);
if (old_data < data_end) {
- btrfs_print_leaf(root, leaf);
+ btrfs_print_leaf(leaf);
printk("slot %d old_data %d data_end %d\n",
slot, old_data, data_end);
BUG_ON(1);
@@ -2564,8 +2582,8 @@ int btrfs_insert_empty_items(struct btrfs_trans_handle *trans,
btrfs_fixup_low_keys(root, path, &disk_key, 1);
}
- if (btrfs_leaf_free_space(root, leaf) < 0) {
- btrfs_print_leaf(root, leaf);
+ if (btrfs_leaf_free_space(root->fs_info, leaf) < 0) {
+ btrfs_print_leaf(leaf);
BUG();
}