summaryrefslogtreecommitdiff
path: root/libbcachefs/btree_cache.c
diff options
context:
space:
mode:
Diffstat (limited to 'libbcachefs/btree_cache.c')
-rw-r--r--libbcachefs/btree_cache.c51
1 files changed, 25 insertions, 26 deletions
diff --git a/libbcachefs/btree_cache.c b/libbcachefs/btree_cache.c
index bdbe21ac..d619f375 100644
--- a/libbcachefs/btree_cache.c
+++ b/libbcachefs/btree_cache.c
@@ -41,7 +41,7 @@ static void __mca_data_free(struct bch_fs *c, struct btree *b)
{
EBUG_ON(btree_node_write_in_flight(b));
- free_pages((unsigned long) b->data, btree_page_order(c));
+ kvpfree(b->data, btree_bytes(c));
b->data = NULL;
bch2_btree_keys_free(b);
}
@@ -53,8 +53,6 @@ static void mca_data_free(struct bch_fs *c, struct btree *b)
list_move(&b->list, &c->btree_cache_freed);
}
-#define PTR_HASH(_k) (bkey_i_to_extent_c(_k)->v._data[0])
-
static const struct rhashtable_params bch_btree_cache_params = {
.head_offset = offsetof(struct btree, hash),
.key_offset = offsetof(struct btree, key.v),
@@ -63,20 +61,18 @@ static const struct rhashtable_params bch_btree_cache_params = {
static void mca_data_alloc(struct bch_fs *c, struct btree *b, gfp_t gfp)
{
- unsigned order = ilog2(btree_pages(c));
-
- b->data = (void *) __get_free_pages(gfp, order);
+ b->data = kvpmalloc(btree_bytes(c), gfp);
if (!b->data)
goto err;
- if (bch2_btree_keys_alloc(b, order, gfp))
+ if (bch2_btree_keys_alloc(b, btree_page_order(c), gfp))
goto err;
c->btree_cache_used++;
list_move(&b->list, &c->btree_cache_freeable);
return;
err:
- free_pages((unsigned long) b->data, order);
+ kvpfree(b->data, btree_bytes(c));
b->data = NULL;
list_move(&b->list, &c->btree_cache_freed);
}
@@ -91,7 +87,6 @@ static struct btree *mca_bucket_alloc(struct bch_fs *c, gfp_t gfp)
six_lock_init(&b->lock);
INIT_LIST_HEAD(&b->list);
INIT_LIST_HEAD(&b->write_blocked);
- INIT_LIST_HEAD(&b->reachable);
mca_data_alloc(c, b, gfp);
return b->data ? b : NULL;
@@ -101,10 +96,6 @@ static struct btree *mca_bucket_alloc(struct bch_fs *c, gfp_t gfp)
void bch2_btree_node_hash_remove(struct bch_fs *c, struct btree *b)
{
- BUG_ON(btree_node_dirty(b));
-
- b->nsets = 0;
-
rhashtable_remove_fast(&c->btree_cache_table, &b->hash,
bch_btree_cache_params);
@@ -112,23 +103,27 @@ void bch2_btree_node_hash_remove(struct bch_fs *c, struct btree *b)
bkey_i_to_extent(&b->key)->v._data[0] = 0;
}
+int __bch2_btree_node_hash_insert(struct bch_fs *c, struct btree *b)
+{
+ return rhashtable_lookup_insert_fast(&c->btree_cache_table, &b->hash,
+ bch_btree_cache_params);
+}
+
int bch2_btree_node_hash_insert(struct bch_fs *c, struct btree *b,
unsigned level, enum btree_id id)
{
int ret;
+
b->level = level;
b->btree_id = id;
- ret = rhashtable_lookup_insert_fast(&c->btree_cache_table, &b->hash,
- bch_btree_cache_params);
- if (ret)
- return ret;
-
mutex_lock(&c->btree_cache_lock);
- list_add(&b->list, &c->btree_cache);
+ ret = __bch2_btree_node_hash_insert(c, b);
+ if (!ret)
+ list_add(&b->list, &c->btree_cache);
mutex_unlock(&c->btree_cache_lock);
- return 0;
+ return ret;
}
__flatten
@@ -155,8 +150,7 @@ static int __btree_node_reclaim(struct bch_fs *c, struct btree *b, bool flush)
if (!six_trylock_write(&b->lock))
goto out_unlock_intent;
- if (btree_node_write_error(b) ||
- btree_node_noevict(b))
+ if (btree_node_noevict(b))
goto out_unlock;
if (!btree_node_may_write(b))
@@ -328,7 +322,7 @@ void bch2_fs_btree_exit(struct bch_fs *c)
if (c->verify_data)
list_move(&c->verify_data->list, &c->btree_cache);
- free_pages((unsigned long) c->verify_ondisk, ilog2(btree_pages(c)));
+ kvpfree(c->verify_ondisk, btree_bytes(c));
#endif
for (i = 0; i < BTREE_ID_NR; i++)
@@ -384,8 +378,7 @@ int bch2_fs_btree_init(struct bch_fs *c)
#ifdef CONFIG_BCACHEFS_DEBUG
mutex_init(&c->verify_lock);
- c->verify_ondisk = (void *)
- __get_free_pages(GFP_KERNEL, ilog2(btree_pages(c)));
+ c->verify_ondisk = kvpmalloc(btree_bytes(c), GFP_KERNEL);
if (!c->verify_ondisk)
return -ENOMEM;
@@ -510,7 +503,7 @@ struct btree *bch2_btree_node_mem_alloc(struct bch_fs *c)
BUG_ON(!six_trylock_intent(&b->lock));
BUG_ON(!six_trylock_write(&b->lock));
out_unlock:
- BUG_ON(bkey_extent_is_data(&b->key.k) && PTR_HASH(&b->key));
+ BUG_ON(btree_node_hashed(b));
BUG_ON(btree_node_write_in_flight(b));
list_del_init(&b->list);
@@ -554,6 +547,12 @@ static noinline struct btree *bch2_btree_node_fill(struct btree_iter *iter,
struct bch_fs *c = iter->c;
struct btree *b;
+ /*
+ * Parent node must be locked, else we could read in a btree node that's
+ * been freed:
+ */
+ BUG_ON(!btree_node_locked(iter, level + 1));
+
b = bch2_btree_node_mem_alloc(c);
if (IS_ERR(b))
return b;