static bool bch_extent_bad_expensive(struct btree *b, const struct bkey *k, unsigned ptr) { struct bucket *g = PTR_BUCKET(b->c, k, ptr); char buf[80]; if (mutex_trylock(&b->c->bucket_lock)) { if (b->c->gc_mark_valid && (!GC_MARK(g) || GC_MARK(g) == GC_MARK_METADATA || (GC_MARK(g) != GC_MARK_DIRTY && KEY_DIRTY(k)))) goto err; if (g->prio == BTREE_PRIO) goto err; mutex_unlock(&b->c->bucket_lock); } return false; err: mutex_unlock(&b->c->bucket_lock); bch_extent_to_text(buf, sizeof(buf), k); btree_bug(b, "inconsistent extent pointer %s:\nbucket %zu pin %i prio %i gen %i last_gc %i mark %llu", buf, PTR_BUCKET_NR(b->c, k, ptr), atomic_read(&g->pin), g->prio, g->gen, g->last_gc, GC_MARK(g)); return true; }
static bool btree_ptr_bad_expensive(struct btree *b, const struct bkey *k) { unsigned i; char buf[80]; struct bucket *g; if (mutex_trylock(&b->c->bucket_lock)) { for (i = 0; i < KEY_PTRS(k); i++) if (ptr_available(b->c, k, i)) { g = PTR_BUCKET(b->c, k, i); if (KEY_DIRTY(k) || g->prio != BTREE_PRIO || (b->c->gc_mark_valid && GC_MARK(g) != GC_MARK_METADATA)) goto err; } mutex_unlock(&b->c->bucket_lock); } return false; err: mutex_unlock(&b->c->bucket_lock); bch_extent_to_text(buf, sizeof(buf), k); btree_bug(b, "inconsistent btree pointer %s: bucket %zi pin %i prio %i gen %i last_gc %i mark %llu", buf, PTR_BUCKET_NR(b->c, k, i), atomic_read(&g->pin), g->prio, g->gen, g->last_gc, GC_MARK(g)); return true; }
bool __bch_btree_ptr_invalid(struct cache_set *c, const struct bkey *k) { char buf[80]; if (!KEY_PTRS(k) || !KEY_SIZE(k) || KEY_DIRTY(k)) goto bad; if (__ptr_invalid(c, k)) goto bad; return false; bad: bch_extent_to_text(buf, sizeof(buf), k); cache_bug(c, "spotted btree ptr %s: %s", buf, bch_ptr_status(c, k)); return true; }
bool __bch_extent_invalid(struct cache_set *c, const struct bkey *k) { char buf[80]; if (!KEY_SIZE(k)) return true; if (KEY_SIZE(k) > KEY_OFFSET(k)) goto bad; if (__ptr_invalid(c, k)) goto bad; return false; bad: bch_extent_to_text(buf, sizeof(buf), k); cache_bug(c, "spotted extent %s: %s", buf, bch_ptr_status(c, k)); return true; }
static void bch_bkey_dump(struct btree_keys *keys, const struct bkey *k) { struct btree *b = container_of(keys, struct btree, keys); unsigned j; char buf[80]; bch_extent_to_text(buf, sizeof(buf), k); printk(" %s", buf); for (j = 0; j < KEY_PTRS(k); j++) { size_t n = PTR_BUCKET_NR(b->c, k, j); printk(" bucket %zu", n); if (n >= b->c->sb.first_bucket && n < b->c->sb.nbuckets) printk(" prio %i", PTR_BUCKET(b->c, k, j)->prio); } printk(" %s\n", bch_ptr_status(b->c, k)); }
static bool bch_extent_invalid(struct btree_keys *bk, const struct bkey *k) { struct btree *b = container_of(bk, struct btree, keys); char buf[80]; if (!KEY_SIZE(k)) return true; if (KEY_SIZE(k) > KEY_OFFSET(k)) goto bad; if (__ptr_invalid(b->c, k)) goto bad; return false; bad: bch_extent_to_text(buf, sizeof(buf), k); cache_bug(b->c, "spotted extent %s: %s", buf, bch_ptr_status(b->c, k)); return true; }