summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2018-01-27 18:54:33 -0500
committerKent Overstreet <kent.overstreet@gmail.com>2018-01-27 19:11:10 -0500
commit4e3f6b028d840a3e45d4cd2b317224760c67f69d (patch)
treee320636c695ee7020356d2f84c3565d1757dedf9
parent1a1d1c2086c73679c56729b848f4fa96ff615dea (diff)
bcachefs: fix btree iterators when btree depth == 3
-rw-r--r--fs/bcachefs/btree_iter.c16
-rw-r--r--fs/bcachefs/btree_iter.h8
-rw-r--r--fs/bcachefs/btree_update_interior.c9
3 files changed, 23 insertions, 10 deletions
diff --git a/fs/bcachefs/btree_iter.c b/fs/bcachefs/btree_iter.c
index ee463f36823c..93689542cf8c 100644
--- a/fs/bcachefs/btree_iter.c
+++ b/fs/bcachefs/btree_iter.c
@@ -510,11 +510,15 @@ static inline void __btree_iter_advance(struct btree_iter *iter)
*/
static void btree_iter_verify_new_node(struct btree_iter *iter, struct btree *b)
{
+ struct btree *parent;
bool parent_locked;
struct bkey_packed *k;
- if (!IS_ENABLED(CONFIG_BCACHEFS_DEBUG) ||
- !iter->nodes[b->level + 1])
+ if (!IS_ENABLED(CONFIG_BCACHEFS_DEBUG))
+ return;
+
+ parent = btree_node_parent(iter, b);
+ if (!parent)
return;
parent_locked = btree_node_locked(iter, b->level + 1);
@@ -523,11 +527,10 @@ static void btree_iter_verify_new_node(struct btree_iter *iter, struct btree *b)
return;
k = bch2_btree_node_iter_peek_all(&iter->node_iters[b->level + 1],
- iter->nodes[b->level + 1]);
+ parent);
if (!k ||
bkey_deleted(k) ||
- bkey_cmp_left_packed(iter->nodes[b->level + 1],
- k, &b->key.k.p)) {
+ bkey_cmp_left_packed(parent, k, &b->key.k.p)) {
char buf[100];
struct bkey uk = bkey_unpack_key(b, k);
@@ -902,7 +905,8 @@ int __must_check __bch2_btree_iter_traverse(struct btree_iter *iter)
* btree_iter_lock_root() comes next and that it can't fail
*/
while (iter->level > depth_want) {
- int ret = iter->nodes[iter->level]
+ int ret = iter->level < BTREE_MAX_DEPTH &&
+ iter->nodes[iter->level]
? btree_iter_down(iter)
: btree_iter_lock_root(iter, depth_want);
if (unlikely(ret)) {
diff --git a/fs/bcachefs/btree_iter.h b/fs/bcachefs/btree_iter.h
index 8feb2a574e29..75105dd3d1f7 100644
--- a/fs/bcachefs/btree_iter.h
+++ b/fs/bcachefs/btree_iter.h
@@ -73,6 +73,14 @@ struct btree_iter {
struct btree_iter *next;
};
+static inline struct btree *btree_node_parent(struct btree_iter *iter,
+ struct btree *b)
+{
+ unsigned level = b->level + 1;
+
+ return level < BTREE_MAX_DEPTH ? iter->nodes[level] : NULL;
+}
+
static inline bool btree_iter_linked(const struct btree_iter *iter)
{
return iter->next != iter;
diff --git a/fs/bcachefs/btree_update_interior.c b/fs/bcachefs/btree_update_interior.c
index 41d78eb480bc..56708ea61770 100644
--- a/fs/bcachefs/btree_update_interior.c
+++ b/fs/bcachefs/btree_update_interior.c
@@ -393,6 +393,7 @@ static struct btree *bch2_btree_node_alloc(struct btree_update *as, unsigned lev
struct bch_fs *c = as->c;
struct btree *b;
+ BUG_ON(level >= BTREE_MAX_DEPTH);
BUG_ON(!as->reserve->nr);
b = as->reserve->b[--as->reserve->nr];
@@ -1344,7 +1345,7 @@ static void btree_split(struct btree_update *as, struct btree *b,
struct btree_iter *iter, struct keylist *keys)
{
struct bch_fs *c = as->c;
- struct btree *parent = iter->nodes[b->level + 1];
+ struct btree *parent = btree_node_parent(iter, b);
struct btree *n1, *n2 = NULL, *n3 = NULL;
u64 start_time = local_clock();
@@ -1600,7 +1601,7 @@ retry:
b = iter->nodes[iter->level];
- parent = iter->nodes[b->level + 1];
+ parent = btree_node_parent(iter, b);
if (!parent)
return 0;
@@ -1737,7 +1738,7 @@ static int __btree_node_rewrite(struct bch_fs *c, struct btree_iter *iter,
struct btree *b, unsigned flags,
struct closure *cl)
{
- struct btree *n, *parent = iter->nodes[b->level + 1];
+ struct btree *n, *parent = btree_node_parent(iter, b);
struct btree_update *as;
as = bch2_btree_update_start(c, iter->btree_id,
@@ -1869,7 +1870,7 @@ static void __bch2_btree_node_update_key(struct bch_fs *c,
btree_interior_update_add_node_reference(as, b);
- parent = iter->nodes[b->level + 1];
+ parent = btree_node_parent(iter, b);
if (parent) {
if (new_hash) {
bkey_copy(&new_hash->key, &new_key->k_i);