diff options
author | Slava Pestov <sviatoslavpestov@gmail.com> | 2014-06-13 11:53:08 -0700 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@gmail.com> | 2017-01-18 20:19:48 -0900 |
commit | 2a79a027d7ca65381cbbd52d555aad18867f42e5 (patch) | |
tree | 2cae10236819fa3095359ca570152e93186e9166 | |
parent | 720a266720ce92540cfbc3f5c61cb968774c2e70 (diff) |
bcache: btree node reserve for tiering
If the source tier is full, btree_check_reserve() would block. This could
prevent tiering from making progress in copying to the destination tier.
Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
-rw-r--r-- | drivers/md/bcache/alloc.c | 2 | ||||
-rw-r--r-- | drivers/md/bcache/bcache.h | 2 | ||||
-rw-r--r-- | drivers/md/bcache/request.c | 30 | ||||
-rw-r--r-- | drivers/md/bcache/request.h | 2 | ||||
-rw-r--r-- | drivers/md/bcache/super.c | 2 | ||||
-rw-r--r-- | drivers/md/bcache/tier.c | 1 |
6 files changed, 35 insertions, 4 deletions
diff --git a/drivers/md/bcache/alloc.c b/drivers/md/bcache/alloc.c index 300aa6d7a7b0..9308c053e9fc 100644 --- a/drivers/md/bcache/alloc.c +++ b/drivers/md/bcache/alloc.c @@ -518,7 +518,7 @@ out: BUG_ON(ca->set->gc_mark_valid && GC_MARK(b) != GC_MARK_DIRTY); - if (reserve <= RESERVE_MOVINGGC_BTREE) + if (reserve <= RESERVE_METADATA_LAST) SET_GC_MARK(b, GC_MARK_METADATA); else SET_GC_MARK(b, GC_MARK_DIRTY); diff --git a/drivers/md/bcache/bcache.h b/drivers/md/bcache/bcache.h index 46524c1edeb3..b5db867a8c35 100644 --- a/drivers/md/bcache/bcache.h +++ b/drivers/md/bcache/bcache.h @@ -443,6 +443,8 @@ struct cached_dev { enum alloc_reserve { RESERVE_PRIO = BTREE_ID_NR, RESERVE_MOVINGGC_BTREE, + RESERVE_TIERING_BTREE, + RESERVE_METADATA_LAST = RESERVE_TIERING_BTREE, RESERVE_MOVINGGC, RESERVE_NONE, RESERVE_NR, diff --git a/drivers/md/bcache/request.c b/drivers/md/bcache/request.c index 8ad057d6a84f..579cc9d289b0 100644 --- a/drivers/md/bcache/request.c +++ b/drivers/md/bcache/request.c @@ -48,6 +48,31 @@ static void bio_csum(struct bio *bio, struct bkey *k) /* Insert data into cache */ +static enum alloc_reserve bch_btree_reserve(struct data_insert_op *op) +{ + if (op->moving_gc) { + /* + * free_inc.size buckets are set aside for moving GC + * btree node allocations. This means that if moving GC + * runs out of new buckets for btree nodes, it will have + * put back at least free_inc.size buckets back on + * free_inc, preventing a deadlock. + * + * XXX: figure out a less stupid way of achieving this + */ + return RESERVE_MOVINGGC_BTREE; + } else if (op->tiering) { + /* + * Tiering needs a btree node reserve because of how + * btree_check_reserve() works -- if the cache tier is + * full, we don't want tiering to block forever. + */ + return RESERVE_TIERING_BTREE; + } + + return BTREE_ID_EXTENTS; +} + /** * bch_data_insert_keys - insert extent btree keys for a write */ @@ -56,12 +81,11 @@ static void bch_data_insert_keys(struct closure *cl) struct data_insert_op *op = container_of(cl, struct data_insert_op, cl); struct bkey *replace_key = op->replace ? &op->replace_key : NULL; enum btree_id id = BTREE_ID_EXTENTS; - enum alloc_reserve reserve = id; + enum alloc_reserve reserve; unsigned i; int ret; - if (op->moving_gc) - reserve = RESERVE_MOVINGGC_BTREE; + reserve = bch_btree_reserve(op); ret = bch_btree_insert(op->c, id, reserve, &op->insert_keys, replace_key, cl, op->flush); diff --git a/drivers/md/bcache/request.h b/drivers/md/bcache/request.h index 94631d33378a..38477c763884 100644 --- a/drivers/md/bcache/request.h +++ b/drivers/md/bcache/request.h @@ -37,6 +37,8 @@ struct data_insert_op { /* Use moving GC reserves for buckets, btree nodes and * open buckets? */ unsigned moving_gc:1; + /* Use tiering reserves for btree nodes? */ + unsigned tiering:1; /* Set on completion */ unsigned replace_collision:1; /* Internal */ diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c index 52879765c6d1..596d87f5e652 100644 --- a/drivers/md/bcache/super.c +++ b/drivers/md/bcache/super.c @@ -1820,6 +1820,8 @@ static int cache_alloc(struct cache *ca) if (!init_fifo(&ca->free[RESERVE_PRIO], prio_buckets(ca), GFP_KERNEL) || !init_fifo(&ca->free[RESERVE_MOVINGGC_BTREE], free_inc_reserve, GFP_KERNEL) || + !init_fifo(&ca->free[RESERVE_TIERING_BTREE], + BTREE_NODE_RESERVE, GFP_KERNEL) || !init_fifo(&ca->free[RESERVE_MOVINGGC], movinggc_reserve, GFP_KERNEL) || !init_fifo(&ca->free[RESERVE_NONE], reserve_none, GFP_KERNEL) || diff --git a/drivers/md/bcache/tier.c b/drivers/md/bcache/tier.c index 6435f321d470..5ff73532996b 100644 --- a/drivers/md/bcache/tier.c +++ b/drivers/md/bcache/tier.c @@ -104,6 +104,7 @@ static void read_tiering(struct cache_set *c) &io->bio.bio, 0, false, false, false, &io->w->key, &io->w->key); + io->op.tiering = 1; io->op.tier = PTR_TIER(c, &w->key, bch_extent_ptrs(&w->key) - 1) + 1; |