diff options
author | Slava Pestov <sviatoslavpestov@gmail.com> | 2014-06-28 18:23:41 -0700 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@gmail.com> | 2016-10-07 09:00:23 -0800 |
commit | 9b1a614c7ca2faa11e035ca5fe436d7d9fdb2dab (patch) | |
tree | db8e101e1bd5a290d94f6e8bc8ca2ce80bbee492 | |
parent | 45aa7e15cd53ff7861c64e35849a0f16c11e11f1 (diff) |
bcache: open bucket performance tuning
- pick_data_bucket() would put contiguous keys in the same bucket which
was counter-productive for tiering. Instead, let tiering set the
write_point field to a counter in the range 0..nr_in_set.
- Increase number of open buckets per tier from 6 to 16. In the future,
this will be configurable. This increases write bandwidth for tiering.
- Increase total number of open buckets from 64 to 256. In the future,
this will be calculated from the number of cache devices, GC generations
and tiers. This fixes a deadlock when moving GC hoards all open buckets,
blocking foreground writes, or vice versa.
Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
-rw-r--r-- | drivers/md/bcache/alloc.c | 9 | ||||
-rw-r--r-- | drivers/md/bcache/bcache.h | 7 | ||||
-rw-r--r-- | drivers/md/bcache/tier.c | 11 |
3 files changed, 22 insertions, 5 deletions
diff --git a/drivers/md/bcache/alloc.c b/drivers/md/bcache/alloc.c index 025f03b84cc5..3c6902f0ae9d 100644 --- a/drivers/md/bcache/alloc.c +++ b/drivers/md/bcache/alloc.c @@ -728,7 +728,10 @@ static struct open_bucket *bch_open_bucket_get(struct cache_set *c, struct closure *cl) { struct open_bucket *ret; - unsigned reserve = (moving_gc ? 0 : OPEN_BUCKETS_MOVING_GC_RESERVE); + unsigned reserve = 0; + + if (!moving_gc) + reserve = OPEN_BUCKETS_MOVING_GC_RESERVE * c->sb.nr_in_set; spin_lock(&c->open_buckets_lock); @@ -815,7 +818,9 @@ retry: for (i = 0; i < ARRAY_SIZE(tier->data_buckets) && (b = tier->data_buckets[i]); i++) { - if (!bkey_cmp(&b->key, &START_KEY(search))) + /* Tiering thread already writes keys in order, maximize + * write bandwidth instead */ + if (tier_idx == 0 && !bkey_cmp(&b->key, &START_KEY(search))) goto found; else if (b->last_write_point == write_point) wp = i; diff --git a/drivers/md/bcache/bcache.h b/drivers/md/bcache/bcache.h index 475638277cc8..380fd1e7528b 100644 --- a/drivers/md/bcache/bcache.h +++ b/drivers/md/bcache/bcache.h @@ -456,7 +456,8 @@ enum alloc_reserve { */ #define BTREE_NODE_RESERVE 8 -#define OPEN_BUCKETS_COUNT 64 +/* Enough for 16 cache devices, 2 tiers and some left over for pipelining */ +#define OPEN_BUCKETS_COUNT 256 /* We don't want open bucket allocations from bch_alloc_gc_sectors() to fail */ #define OPEN_BUCKETS_MOVING_GC_RESERVE NUM_GC_GENS @@ -592,10 +593,12 @@ struct gc_stat { #define CACHE_SET_STOPPING 1 #define CACHE_SET_RUNNING 2 +#define TIER_OPEN_BUCKETS_COUNT 16 + struct cache_tier { unsigned nr_devices; struct cache *devices[MAX_CACHES_PER_SET]; - struct open_bucket *data_buckets[6]; + struct open_bucket *data_buckets[TIER_OPEN_BUCKETS_COUNT]; }; struct prio_clock { diff --git a/drivers/md/bcache/tier.c b/drivers/md/bcache/tier.c index 5ff73532996b..180cf1463046 100644 --- a/drivers/md/bcache/tier.c +++ b/drivers/md/bcache/tier.c @@ -66,12 +66,15 @@ static void read_tiering(struct cache_set *c) struct moving_io *io; struct closure cl; struct moving_io_stats stats; + unsigned write_point; trace_bcache_tiering_start(c); closure_init_stack(&cl); memset(&stats, 0, sizeof(stats)); + write_point = 0; + /* XXX: if we error, background writeback could stall indefinitely */ c->tiering_keys.last_scanned = ZERO_KEY; @@ -101,7 +104,7 @@ static void read_tiering(struct cache_set *c) io->stats = &stats; bch_data_insert_op_init(&io->op, c, c->tiering_wq, - &io->bio.bio, 0, + &io->bio.bio, write_point, false, false, false, &io->w->key, &io->w->key); io->op.tiering = 1; @@ -113,6 +116,12 @@ static void read_tiering(struct cache_set *c) KEY_SIZE(&w->key) << 9); closure_call(&io->cl, bch_data_move, NULL, &cl); + + /* Try to stripe writes across cache devices by sending them + * to different open buckets */ + write_point++; + if (write_point == c->sb.nr_in_set) + write_point = 0; } if (0) { |