diff options
author | Kent Overstreet <kmo@daterainc.com> | 2014-03-17 16:55:55 -0700 |
---|---|---|
committer | Kent Overstreet <kmo@daterainc.com> | 2014-03-18 12:23:36 -0700 |
commit | 2531d9ee61fa08a5a9ab8f002c50779888d232c7 (patch) | |
tree | 4a75259d27010a2b48c0aca0e5b490060db81f75 /drivers/md/bcache/btree.c | |
parent | 0a63b66db566cffdf90182eb6e66fdd4d0479e63 (diff) | |
download | linux-2531d9ee61fa08a5a9ab8f002c50779888d232c7.tar.gz linux-2531d9ee61fa08a5a9ab8f002c50779888d232c7.tar.bz2 linux-2531d9ee61fa08a5a9ab8f002c50779888d232c7.zip |
bcache: Kill unused freelist
This was originally added as at optimization that for various reasons isn't
needed anymore, but it does add a lot of nasty corner cases (and it was
responsible for some recently fixed bugs). Just get rid of it now.
Signed-off-by: Kent Overstreet <kmo@daterainc.com>
Diffstat (limited to 'drivers/md/bcache/btree.c')
-rw-r--r-- | drivers/md/bcache/btree.c | 41 |
1 files changed, 37 insertions, 4 deletions
diff --git a/drivers/md/bcache/btree.c b/drivers/md/bcache/btree.c index be90596a9e2a..4c340c85b122 100644 --- a/drivers/md/bcache/btree.c +++ b/drivers/md/bcache/btree.c @@ -1641,7 +1641,7 @@ static void btree_gc_start(struct cache_set *c) mutex_unlock(&c->bucket_lock); } -size_t bch_btree_gc_finish(struct cache_set *c) +static size_t bch_btree_gc_finish(struct cache_set *c) { size_t available = 0; struct bucket *b; @@ -1703,9 +1703,6 @@ size_t bch_btree_gc_finish(struct cache_set *c) if (!GC_MARK(b) || GC_MARK(b) == GC_MARK_RECLAIMABLE) available++; - - if (!GC_MARK(b)) - bch_bucket_add_unused(ca, b); } } @@ -1836,6 +1833,42 @@ int bch_btree_check(struct cache_set *c) return btree_root(check_recurse, c, &op); } +void bch_initial_gc_finish(struct cache_set *c) +{ + struct cache *ca; + struct bucket *b; + unsigned i; + + bch_btree_gc_finish(c); + + mutex_lock(&c->bucket_lock); + + /* + * We need to put some unused buckets directly on the prio freelist in + * order to get the allocator thread started - it needs freed buckets in + * order to rewrite the prios and gens, and it needs to rewrite prios + * and gens in order to free buckets. + * + * This is only safe for buckets that have no live data in them, which + * there should always be some of. + */ + for_each_cache(ca, c, i) { + for_each_bucket(b, ca) { + if (fifo_full(&ca->free[RESERVE_PRIO])) + break; + + if (bch_can_invalidate_bucket(ca, b) && + !GC_MARK(b)) { + __bch_invalidate_one_bucket(ca, b); + fifo_push(&ca->free[RESERVE_PRIO], + b - ca->buckets); + } + } + } + + mutex_unlock(&c->bucket_lock); +} + /* Btree insertion */ static bool btree_insert_key(struct btree *b, struct bkey *k, |