diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2018-01-27 18:54:33 -0500 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@gmail.com> | 2018-01-27 19:11:10 -0500 |
commit | 4e3f6b028d840a3e45d4cd2b317224760c67f69d (patch) | |
tree | e320636c695ee7020356d2f84c3565d1757dedf9 | |
parent | 1a1d1c2086c73679c56729b848f4fa96ff615dea (diff) |
bcachefs: fix btree iterators when btree depth == 3
-rw-r--r-- | fs/bcachefs/btree_iter.c | 16 | ||||
-rw-r--r-- | fs/bcachefs/btree_iter.h | 8 | ||||
-rw-r--r-- | fs/bcachefs/btree_update_interior.c | 9 |
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); |