static bool bch_extent_bad(struct btree_keys *bk, const struct bkey *k) { struct btree *b = container_of(bk, struct btree, keys); struct bucket *g; unsigned i, stale; if (!KEY_PTRS(k) || bch_extent_invalid(bk, k)) return true; for (i = 0; i < KEY_PTRS(k); i++) if (!ptr_available(b->c, k, i)) return true; if (!expensive_debug_checks(b->c) && KEY_DIRTY(k)) return false; for (i = 0; i < KEY_PTRS(k); i++) { g = PTR_BUCKET(b->c, k, i); stale = ptr_stale(b->c, k, i); btree_bug_on(stale > 96, b, "key too stale: %i, need_gc %u", stale, b->c->need_gc); btree_bug_on(stale && KEY_DIRTY(k) && KEY_SIZE(k), b, "stale dirty pointer"); if (stale) return true; if (expensive_debug_checks(b->c) && bch_extent_bad_expensive(b, k, i)) return true; } return false; }
static bool bch_btree_ptr_bad(struct btree_keys *bk, const struct bkey *k) { struct btree *b = container_of(bk, struct btree, keys); unsigned i; if (!bkey_cmp(k, &ZERO_KEY) || !KEY_PTRS(k) || bch_ptr_invalid(bk, k)) return true; for (i = 0; i < KEY_PTRS(k); i++) if (!ptr_available(b->c, k, i) || ptr_stale(b->c, k, i)) return true; if (expensive_debug_checks(b->c) && btree_ptr_bad_expensive(b, k)) return true; return false; }
long bch_bucket_alloc(struct cache *ca, unsigned reserve, bool wait) { DEFINE_WAIT(w); struct bucket *b; long r; /* fastpath */ if (fifo_pop(&ca->free[RESERVE_NONE], r) || fifo_pop(&ca->free[reserve], r)) goto out; if (!wait) { trace_bcache_alloc_fail(ca, reserve); return -1; } do { prepare_to_wait(&ca->set->bucket_wait, &w, TASK_UNINTERRUPTIBLE); mutex_unlock(&ca->set->bucket_lock); schedule(); mutex_lock(&ca->set->bucket_lock); } while (!fifo_pop(&ca->free[RESERVE_NONE], r) && !fifo_pop(&ca->free[reserve], r)); finish_wait(&ca->set->bucket_wait, &w); out: wake_up_process(ca->alloc_thread); trace_bcache_alloc(ca, reserve); if (expensive_debug_checks(ca->set)) { size_t iter; long i; unsigned j; for (iter = 0; iter < prio_buckets(ca) * 2; iter++) BUG_ON(ca->prio_buckets[iter] == (uint64_t) r); for (j = 0; j < RESERVE_NR; j++) fifo_for_each(i, &ca->free[j], iter) BUG_ON(i == r); fifo_for_each(i, &ca->free_inc, iter) BUG_ON(i == r); } b = ca->buckets + r; BUG_ON(atomic_read(&b->pin) != 1); SET_GC_SECTORS_USED(b, ca->sb.bucket_size); if (reserve <= RESERVE_PRIO) { SET_GC_MARK(b, GC_MARK_METADATA); SET_GC_MOVE(b, 0); b->prio = BTREE_PRIO; } else { SET_GC_MARK(b, GC_MARK_RECLAIMABLE); SET_GC_MOVE(b, 0); b->prio = INITIAL_PRIO; } return r; }