summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2016-09-05 19:22:06 -0800
committerKent Overstreet <kent.overstreet@gmail.com>2016-09-08 19:07:20 -0800
commit24203d787c2b5ee1d69073aea935905848f02c77 (patch)
tree402cd665cf8102fd32dd7fd9a759da5785aa940c
parentf4543f9c65ac340c38742d0307f6aeef080b7119 (diff)
bcache: hack to deal with multiple promote operations racing
-rw-r--r--drivers/md/bcache/io.c6
-rw-r--r--drivers/md/bcache/move.c7
-rw-r--r--drivers/md/bcache/move.h1
3 files changed, 14 insertions, 0 deletions
diff --git a/drivers/md/bcache/io.c b/drivers/md/bcache/io.c
index 40f51b7340bd..fb5bdab51f72 100644
--- a/drivers/md/bcache/io.c
+++ b/drivers/md/bcache/io.c
@@ -1519,6 +1519,11 @@ void bch_read_extent_iter(struct cache_set *c, struct bch_read_bio *orig,
k.k->p.offset < bvec_iter_end_sector(iter));
/* only promote if we're not reading from the fastest tier: */
+
+ /*
+ * XXX: multiple promotes can race with each other, wastefully. Keep a
+ * list of outstanding promotes?
+ */
if ((flags & BCH_READ_PROMOTE) && pick->ca->mi.tier) {
/*
* biovec needs to be big enough to hold decompressed data, if
@@ -1629,6 +1634,7 @@ void bch_read_extent_iter(struct cache_set *c, struct bch_read_bio *orig,
&c->promote_write_point,
k, NULL,
BCH_WRITE_ALLOC_NOWAIT);
+ promote_op->write.promote = true;
if (rbio->crc.compression_type) {
promote_op->write.op.flags |= BCH_WRITE_DATA_COMPRESSED;
diff --git a/drivers/md/bcache/move.c b/drivers/md/bcache/move.c
index bb42e8dca9dd..ba2351214fd9 100644
--- a/drivers/md/bcache/move.c
+++ b/drivers/md/bcache/move.c
@@ -80,6 +80,12 @@ static int bch_migrate_index_update(struct bch_write_op *op)
bch_cut_back(insert->k.p, &new.k.k);
e = bkey_i_to_s_extent(&new.k);
+ /* hack - promotes can race: */
+ if (m->promote)
+ extent_for_each_ptr(bkey_i_to_s_extent(insert), ptr)
+ if (bch_extent_has_device(e.c, ptr->dev))
+ goto nomatch;
+
ptr = bch_migrate_matching_ptr(m, e);
if (ptr) {
if (m->move)
@@ -127,6 +133,7 @@ void bch_migrate_write_init(struct cache_set *c,
{
bkey_reassemble(&m->key, k);
+ m->promote = false;
m->move = move_ptr != NULL;
if (move_ptr)
m->move_ptr = *move_ptr;
diff --git a/drivers/md/bcache/move.h b/drivers/md/bcache/move.h
index ab7829d1cfd1..0f8f787a5168 100644
--- a/drivers/md/bcache/move.h
+++ b/drivers/md/bcache/move.h
@@ -63,6 +63,7 @@ void bch_moving_wait(struct moving_context *);
struct migrate_write {
BKEY_PADDED(key);
+ bool promote;
bool move;
struct bch_extent_ptr move_ptr;
struct bch_write_op op;