diff options
-rw-r--r-- | fs/bcachefs/btree_iter.c | 94 | ||||
-rw-r--r-- | fs/bcachefs/btree_key_cache.c | 25 | ||||
-rw-r--r-- | fs/bcachefs/btree_key_cache.h | 2 | ||||
-rw-r--r-- | fs/bcachefs/sysfs.c | 11 |
4 files changed, 110 insertions, 22 deletions
diff --git a/fs/bcachefs/btree_iter.c b/fs/bcachefs/btree_iter.c index 592663a00182..2bd02e804b76 100644 --- a/fs/bcachefs/btree_iter.c +++ b/fs/bcachefs/btree_iter.c @@ -185,6 +185,14 @@ static inline bool btree_iter_get_locks(struct btree_iter *iter, return iter->uptodate < BTREE_ITER_NEED_RELOCK; } +static struct bpos btree_node_pos(struct btree_bkey_cached_common *_b, + enum btree_iter_type type) +{ + return type != BTREE_ITER_CACHED + ? container_of(_b, struct btree, c)->key.k.p + : container_of(_b, struct bkey_cached, c)->key.pos; +} + /* Slowpath: */ bool __bch2_btree_node_lock(struct btree *b, struct bpos pos, unsigned level, struct btree_iter *iter, @@ -253,7 +261,8 @@ bool __bch2_btree_node_lock(struct btree *b, struct bpos pos, if (iter->btree_id == linked->btree_id && btree_node_locked(linked, level) && - bkey_cmp(pos, linked->l[level].b->key.k.p) <= 0) + bkey_cmp(pos, btree_node_pos((void *) linked->l[level].b, + btree_iter_type(linked))) <= 0) ret = false; /* @@ -435,6 +444,22 @@ void bch2_trans_unlock(struct btree_trans *trans) #ifdef CONFIG_BCACHEFS_DEBUG +static void bch2_btree_iter_verify_cached(struct btree_iter *iter) +{ + struct bkey_cached *ck; + bool locked = btree_node_locked(iter, 0); + + if (!bch2_btree_node_relock(iter, 0)) + return; + + ck = (void *) iter->l[0].b; + BUG_ON(ck->key.btree_id != iter->btree_id || + bkey_cmp(ck->key.pos, iter->pos)); + + if (!locked) + btree_node_unlock(iter, 0); +} + static void bch2_btree_iter_verify_level(struct btree_iter *iter, unsigned level) { @@ -449,6 +474,12 @@ static void bch2_btree_iter_verify_level(struct btree_iter *iter, if (!debug_check_iterators(iter->trans->c)) return; + if (btree_iter_type(iter) == BTREE_ITER_CACHED) { + if (!level) + bch2_btree_iter_verify_cached(iter); + return; + } + BUG_ON(iter->level < iter->min_depth); if (!btree_iter_node(iter, level)) @@ -1257,13 +1288,14 @@ int __must_check __bch2_btree_iter_traverse(struct btree_iter *iter) return ret; } -static inline void bch2_btree_iter_checks(struct btree_iter *iter, - enum btree_iter_type type) +static inline void bch2_btree_iter_checks(struct btree_iter *iter) { + enum btree_iter_type type = btree_iter_type(iter); + EBUG_ON(iter->btree_id >= BTREE_ID_NR); - EBUG_ON(btree_iter_type(iter) != type); - BUG_ON(type == BTREE_ITER_KEYS && + BUG_ON((type == BTREE_ITER_KEYS || + type == BTREE_ITER_CACHED) && (bkey_cmp(iter->pos, bkey_start_pos(&iter->k)) < 0 || bkey_cmp(iter->pos, iter->k.p) > 0)); @@ -1278,7 +1310,8 @@ struct btree *bch2_btree_iter_peek_node(struct btree_iter *iter) struct btree *b; int ret; - bch2_btree_iter_checks(iter, BTREE_ITER_NODES); + EBUG_ON(btree_iter_type(iter) != BTREE_ITER_NODES); + bch2_btree_iter_checks(iter); if (iter->uptodate == BTREE_ITER_UPTODATE) return iter->l[iter->level].b; @@ -1306,7 +1339,8 @@ struct btree *bch2_btree_iter_next_node(struct btree_iter *iter) struct btree *b; int ret; - bch2_btree_iter_checks(iter, BTREE_ITER_NODES); + EBUG_ON(btree_iter_type(iter) != BTREE_ITER_NODES); + bch2_btree_iter_checks(iter); /* already got to end? */ if (!btree_iter_node(iter, iter->level)) @@ -1534,7 +1568,8 @@ struct bkey_s_c bch2_btree_iter_peek(struct btree_iter *iter) struct bkey_s_c k; int ret; - bch2_btree_iter_checks(iter, BTREE_ITER_KEYS); + EBUG_ON(btree_iter_type(iter) != BTREE_ITER_KEYS); + bch2_btree_iter_checks(iter); if (iter->uptodate == BTREE_ITER_UPTODATE && !bkey_deleted(&iter->k)) @@ -1621,7 +1656,8 @@ struct bkey_s_c bch2_btree_iter_peek_with_updates(struct btree_iter *iter) struct bkey_s_c k; int ret; - bch2_btree_iter_checks(iter, BTREE_ITER_KEYS); + EBUG_ON(btree_iter_type(iter) != BTREE_ITER_KEYS); + bch2_btree_iter_checks(iter); while (1) { ret = bch2_btree_iter_traverse(iter); @@ -1681,7 +1717,8 @@ struct bkey_s_c bch2_btree_iter_peek_prev(struct btree_iter *iter) struct bkey_s_c k; int ret; - bch2_btree_iter_checks(iter, BTREE_ITER_KEYS); + EBUG_ON(btree_iter_type(iter) != BTREE_ITER_KEYS); + bch2_btree_iter_checks(iter); if (iter->uptodate == BTREE_ITER_UPTODATE && !bkey_deleted(&iter->k)) @@ -1717,7 +1754,8 @@ struct bkey_s_c bch2_btree_iter_prev(struct btree_iter *iter) { struct bpos pos = bkey_start_pos(&iter->k); - bch2_btree_iter_checks(iter, BTREE_ITER_KEYS); + EBUG_ON(btree_iter_type(iter) != BTREE_ITER_KEYS); + bch2_btree_iter_checks(iter); if (unlikely(!bkey_cmp(pos, POS_MIN))) return bkey_s_c_null; @@ -1798,7 +1836,8 @@ struct bkey_s_c bch2_btree_iter_peek_slot(struct btree_iter *iter) struct bkey_s_c k; int ret; - bch2_btree_iter_checks(iter, BTREE_ITER_KEYS); + EBUG_ON(btree_iter_type(iter) != BTREE_ITER_KEYS); + bch2_btree_iter_checks(iter); if (iter->uptodate == BTREE_ITER_UPTODATE) return btree_iter_peek_uptodate(iter); @@ -1844,7 +1883,8 @@ struct bkey_s_c bch2_btree_iter_peek_cached(struct btree_iter *iter) struct bkey_cached *ck; int ret; - bch2_btree_iter_checks(iter, BTREE_ITER_CACHED); + EBUG_ON(btree_iter_type(iter) != BTREE_ITER_CACHED); + bch2_btree_iter_checks(iter); ret = bch2_btree_iter_traverse(iter); if (unlikely(ret)) @@ -2324,6 +2364,15 @@ int bch2_trans_exit(struct btree_trans *trans) return trans->error ? -EIO : 0; } +static void bch2_btree_iter_node_to_text(struct printbuf *out, + struct btree_bkey_cached_common *_b, + enum btree_iter_type type) +{ + pr_buf(out, " %px l=%u %s:", + _b, _b->level, bch2_btree_ids[_b->btree_id]); + bch2_bpos_to_text(out, btree_node_pos(_b, type)); +} + void bch2_btree_trans_to_text(struct printbuf *out, struct bch_fs *c) { #ifdef CONFIG_BCACHEFS_DEBUG @@ -2348,11 +2397,11 @@ void bch2_btree_trans_to_text(struct printbuf *out, struct bch_fs *c) for (l = 0; l < BTREE_MAX_DEPTH; l++) { if (btree_node_locked(iter, l)) { - b = iter->l[l].b; - - pr_buf(out, " %px %s l=%u ", - b, btree_node_intent_locked(iter, l) ? "i" : "r", l); - bch2_bpos_to_text(out, b->key.k.p); + pr_buf(out, " %s l=%u ", + btree_node_intent_locked(iter, l) ? "i" : "r", l); + bch2_btree_iter_node_to_text(out, + (void *) iter->l[l].b, + btree_iter_type(iter)); pr_buf(out, "\n"); } } @@ -2366,10 +2415,11 @@ void bch2_btree_trans_to_text(struct printbuf *out, struct bch_fs *c) bch2_btree_ids[trans->locking_btree_id]); bch2_bpos_to_text(out, trans->locking_pos); - pr_buf(out, " node %px l=%u %s:", - b, b->c.level, - bch2_btree_ids[b->c.btree_id]); - bch2_bpos_to_text(out, b->key.k.p); + + pr_buf(out, " node "); + bch2_btree_iter_node_to_text(out, + (void *) b, + btree_iter_type(&trans->iters[trans->locking_iter_idx])); pr_buf(out, "\n"); } } diff --git a/fs/bcachefs/btree_key_cache.c b/fs/bcachefs/btree_key_cache.c index 2feff59e755a..1be01035869f 100644 --- a/fs/bcachefs/btree_key_cache.c +++ b/fs/bcachefs/btree_key_cache.c @@ -1,5 +1,6 @@ #include "bcachefs.h" +#include "btree_cache.h" #include "btree_iter.h" #include "btree_key_cache.h" #include "btree_locking.h" @@ -492,3 +493,27 @@ int bch2_fs_btree_key_cache_init(struct btree_key_cache *c) { return rhashtable_init(&c->table, &bch2_btree_key_cache_params); } + +void bch2_btree_key_cache_to_text(struct printbuf *out, struct btree_key_cache *c) +{ + struct bucket_table *tbl; + struct bkey_cached *ck; + struct rhash_head *pos; + size_t i; + + mutex_lock(&c->lock); + tbl = rht_dereference_rcu(c->table.tbl, &c->table); + + for (i = 0; i < tbl->size; i++) { + rht_for_each_entry_rcu(ck, pos, tbl, i, hash) { + pr_buf(out, "%s:", + bch2_btree_ids[ck->key.btree_id]); + bch2_bpos_to_text(out, ck->key.pos); + + if (test_bit(BKEY_CACHED_DIRTY, &ck->flags)) + pr_buf(out, " journal seq %llu", ck->journal.seq); + pr_buf(out, "\n"); + } + } + mutex_unlock(&c->lock); +} diff --git a/fs/bcachefs/btree_key_cache.h b/fs/bcachefs/btree_key_cache.h index fbc29336091f..b1756c6c622c 100644 --- a/fs/bcachefs/btree_key_cache.h +++ b/fs/bcachefs/btree_key_cache.h @@ -20,4 +20,6 @@ void bch2_fs_btree_key_cache_exit(struct btree_key_cache *); void bch2_fs_btree_key_cache_init_early(struct btree_key_cache *); int bch2_fs_btree_key_cache_init(struct btree_key_cache *); +void bch2_btree_key_cache_to_text(struct printbuf *, struct btree_key_cache *); + #endif /* _BCACHEFS_BTREE_KEY_CACHE_H */ diff --git a/fs/bcachefs/sysfs.c b/fs/bcachefs/sysfs.c index bda9eb1598b8..67c0f6d2b219 100644 --- a/fs/bcachefs/sysfs.c +++ b/fs/bcachefs/sysfs.c @@ -14,6 +14,7 @@ #include "btree_cache.h" #include "btree_io.h" #include "btree_iter.h" +#include "btree_key_cache.h" #include "btree_update.h" #include "btree_update_interior.h" #include "btree_gc.h" @@ -165,6 +166,7 @@ read_attribute(journal_debug); read_attribute(journal_pins); read_attribute(btree_updates); read_attribute(dirty_btree_nodes); +read_attribute(btree_key_cache); read_attribute(btree_transactions); read_attribute(internal_uuid); @@ -401,6 +403,14 @@ SHOW(bch2_fs) if (attr == &sysfs_dirty_btree_nodes) return bch2_dirty_btree_nodes_print(c, buf); + + if (attr == &sysfs_btree_key_cache) { + struct printbuf out = _PBUF(buf, PAGE_SIZE); + + bch2_btree_key_cache_to_text(&out, &c->btree_key_cache); + return out.pos - buf; + } + if (attr == &sysfs_btree_transactions) { struct printbuf out = _PBUF(buf, PAGE_SIZE); @@ -571,6 +581,7 @@ struct attribute *bch2_fs_internal_files[] = { &sysfs_journal_pins, &sysfs_btree_updates, &sysfs_dirty_btree_nodes, + &sysfs_btree_key_cache, &sysfs_btree_transactions, &sysfs_read_realloc_races, |