diff options
Diffstat (limited to 'libbcachefs/btree_cache.c')
-rw-r--r-- | libbcachefs/btree_cache.c | 27 |
1 files changed, 22 insertions, 5 deletions
diff --git a/libbcachefs/btree_cache.c b/libbcachefs/btree_cache.c index 78e36299..0bde449e 100644 --- a/libbcachefs/btree_cache.c +++ b/libbcachefs/btree_cache.c @@ -57,10 +57,20 @@ static void btree_node_data_free(struct bch_fs *c, struct btree *b) list_move(&b->list, &bc->freed); } +static int bch2_btree_cache_cmp_fn(struct rhashtable_compare_arg *arg, + const void *obj) +{ + const struct btree *b = obj; + const u64 *v = arg->key; + + return PTR_HASH(&b->key) == *v ? 0 : 1; +} + static const struct rhashtable_params bch_btree_cache_params = { .head_offset = offsetof(struct btree, hash), .key_offset = offsetof(struct btree, key.v), .key_len = sizeof(struct bch_extent_ptr), + .obj_cmpfn = bch2_btree_cache_cmp_fn, }; static void btree_node_data_alloc(struct bch_fs *c, struct btree *b, gfp_t gfp) @@ -337,6 +347,9 @@ void bch2_fs_btree_cache_exit(struct bch_fs *c) while (!list_empty(&bc->live)) { b = list_first_entry(&bc->live, struct btree, list); + BUG_ON(btree_node_read_in_flight(b) || + btree_node_write_in_flight(b)); + if (btree_node_dirty(b)) bch2_btree_complete_write(c, b, btree_current_write(b)); clear_btree_node_dirty(b); @@ -736,7 +749,7 @@ struct btree *bch2_btree_node_get_sibling(struct bch_fs *c, struct btree *ret; unsigned level = b->level; - parent = iter->nodes[level + 1]; + parent = btree_iter_node(iter, level + 1); if (!parent) return NULL; @@ -745,7 +758,7 @@ struct btree *bch2_btree_node_get_sibling(struct bch_fs *c, return ERR_PTR(-EINTR); } - node_iter = iter->node_iters[parent->level]; + node_iter = iter->l[parent->level].iter; k = bch2_btree_node_iter_peek_all(&node_iter, parent); BUG_ON(bkey_cmp_left_packed(parent, k, &b->key.k.p)); @@ -774,9 +787,13 @@ struct btree *bch2_btree_node_get_sibling(struct bch_fs *c, ret = bch2_btree_node_get(c, iter, &tmp.k, level, SIX_LOCK_intent); } - if (!IS_ERR(ret) && !bch2_btree_node_relock(iter, level)) { - six_unlock_intent(&ret->lock); - ret = ERR_PTR(-EINTR); + if (!bch2_btree_node_relock(iter, level)) { + btree_iter_set_dirty(iter, BTREE_ITER_NEED_RELOCK); + + if (!IS_ERR(ret)) { + six_unlock_intent(&ret->lock); + ret = ERR_PTR(-EINTR); + } } return ret; |