summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2016-09-01 16:00:20 -0800
committerKent Overstreet <kent.overstreet@gmail.com>2016-09-08 19:07:20 -0800
commita35f8e611b7f3bdf3173751de98e122db76fb693 (patch)
treed2a6d9d6340858705c77de40ddd6948b7cd02a11
parentaff477f5af5e69778712e03c7b48c28cf1f9186c (diff)
bcache: replace bch_extent_cmpxchg() for migrate
-rw-r--r--drivers/md/bcache/io.c16
-rw-r--r--drivers/md/bcache/migrate.c38
-rw-r--r--drivers/md/bcache/move.c138
-rw-r--r--drivers/md/bcache/move.h11
-rw-r--r--drivers/md/bcache/movinggc.c47
-rw-r--r--drivers/md/bcache/tier.c12
6 files changed, 178 insertions, 84 deletions
diff --git a/drivers/md/bcache/io.c b/drivers/md/bcache/io.c
index 7ec4b627d7d4..250de2586a90 100644
--- a/drivers/md/bcache/io.c
+++ b/drivers/md/bcache/io.c
@@ -51,18 +51,16 @@ void bch_bio_submit_work(struct work_struct *work)
{
struct cache_set *c = container_of(work, struct cache_set,
bio_submit_work);
+ struct bio_list bl;
struct bio *bio;
- while (1) {
- spin_lock(&c->bio_submit_lock);
- bio = bio_list_pop(&c->bio_submit_list);
- spin_unlock(&c->bio_submit_lock);
-
- if (!bio)
- break;
+ spin_lock(&c->bio_submit_lock);
+ bl = c->bio_submit_list;
+ bio_list_init(&c->bio_submit_list);
+ spin_unlock(&c->bio_submit_lock);
- bch_generic_make_request(bio, c);
- }
+ while ((bio = bio_list_pop(&bl)))
+ generic_make_request(bio);
}
/* Allocate, free from mempool: */
diff --git a/drivers/md/bcache/migrate.c b/drivers/md/bcache/migrate.c
index 9241cca3fc5d..1169f8fc28a1 100644
--- a/drivers/md/bcache/migrate.c
+++ b/drivers/md/bcache/migrate.c
@@ -22,15 +22,6 @@ static bool migrate_data_pred(struct scan_keylist *kl, struct bkey_s_c k)
ca->sb.nr_this_dev);
}
-static void bch_extent_drop_dev_ptrs(struct bkey_s_extent e, unsigned dev)
-{
- struct bch_extent_ptr *ptr;
-
- extent_for_each_ptr_backwards(e, ptr)
- if (ptr->dev == dev)
- bch_extent_drop_ptr(e, ptr);
-}
-
static int issue_migration_move(struct cache *ca,
struct moving_context *ctxt,
struct bkey_s_c k,
@@ -40,31 +31,23 @@ static int issue_migration_move(struct cache *ca,
struct cache_set *c = ca->set;
struct moving_io *io;
struct disk_reservation res;
+ const struct bch_extent_ptr *ptr;
if (bch_disk_reservation_get(c, &res, k.k->size, 0))
return -ENOSPC;
- io = moving_io_alloc(k);
+ extent_for_each_ptr(bkey_s_c_to_extent(k), ptr)
+ if (ptr->dev == ca->sb.nr_this_dev)
+ goto found;
+
+ BUG();
+found:
+ io = moving_io_alloc(c, q, &c->migration_write_point, k, ptr);
if (!io) {
bch_disk_reservation_put(c, &res);
return -ENOMEM;
}
- /* This also copies k into the write op's replace_key and insert_key */
-
- bch_replace_init(&io->replace, k);
-
- bch_write_op_init(&io->op, c, &io->wbio, res,
- &c->migration_write_point,
- k, &io->replace.hook, NULL,
- 0);
- io->op.nr_replicas = 1;
-
- io->op.io_wq = q->wq;
-
- bch_extent_drop_dev_ptrs(bkey_i_to_s_extent(&io->op.insert_key),
- ca->sb.nr_this_dev);
-
bch_data_move(q, ctxt, io);
(*seen_key_count)++;
@@ -370,12 +353,15 @@ static int bch_flag_key_bad(struct btree_iter *iter,
{
BKEY_PADDED(key) tmp;
struct bkey_s_extent e;
+ struct bch_extent_ptr *ptr;
struct cache_set *c = ca->set;
bkey_reassemble(&tmp.key, orig.s_c);
e = bkey_i_to_s_extent(&tmp.key);
- bch_extent_drop_dev_ptrs(e, ca->sb.nr_this_dev);
+ extent_for_each_ptr_backwards(e, ptr)
+ if (ptr->dev == ca->sb.nr_this_dev)
+ bch_extent_drop_ptr(e, ptr);
/*
* If the new extent no longer has any pointers, bch_extent_normalize()
diff --git a/drivers/md/bcache/move.c b/drivers/md/bcache/move.c
index bbfcbdae2f37..1099cc395e05 100644
--- a/drivers/md/bcache/move.c
+++ b/drivers/md/bcache/move.c
@@ -1,6 +1,7 @@
#include "bcache.h"
#include "btree_gc.h"
+#include "btree_update.h"
#include "buckets.h"
#include "io.h"
#include "move.h"
@@ -9,6 +10,113 @@
#include <trace/events/bcache.h>
+static struct bch_extent_ptr *bkey_find_ptr(struct cache_set *c,
+ struct bkey_s_extent e,
+ struct bch_extent_ptr ptr)
+{
+ struct bch_extent_ptr *ptr2;
+ struct cache_member_rcu *mi;
+ unsigned bucket_bits;
+
+ mi = cache_member_info_get(c);
+ bucket_bits = ilog2(mi->m[ptr.dev].bucket_size);
+ cache_member_info_put();
+
+ extent_for_each_ptr(e, ptr2)
+ if (ptr2->dev == ptr.dev &&
+ ptr2->gen == ptr.gen &&
+ (ptr2->offset >> bucket_bits) ==
+ (ptr.offset >> bucket_bits))
+ return ptr2;
+
+ return NULL;
+}
+
+static struct bch_extent_ptr *bch_migrate_matching_ptr(struct moving_io *io,
+ struct bkey_s_extent e)
+{
+ const struct bch_extent_ptr *ptr;
+ struct bch_extent_ptr *ret;
+
+ if (io->move)
+ ret = bkey_find_ptr(io->op.c, e, io->move_ptr);
+ else
+ extent_for_each_ptr(bkey_i_to_s_c_extent(&io->key), ptr)
+ if ((ret = bkey_find_ptr(io->op.c, e, *ptr)))
+ break;
+
+ return ret;
+}
+
+static int bch_migrate_index_update(struct bch_write_op *op)
+{
+ struct cache_set *c = op->c;
+ struct moving_io *io = container_of(op, struct moving_io, op);
+ struct keylist *keys = &op->insert_keys;
+ struct btree_iter iter;
+ int ret = 0;
+
+ bch_btree_iter_init_intent(&iter, c, BTREE_ID_EXTENTS,
+ bkey_start_pos(&bch_keylist_front(keys)->k));
+
+ while (1) {
+ struct bkey_i *insert = bch_keylist_front(keys);
+ struct bkey_s_c k = bch_btree_iter_peek_with_holes(&iter);
+ struct bch_extent_ptr *ptr;
+ struct bkey_s_extent e;
+ BKEY_PADDED(k) new;
+
+ if (!k.k) {
+ ret = bch_btree_iter_unlock(&iter);
+ break;
+ }
+
+ if (!bkey_extent_is_data(k.k))
+ goto nomatch;
+
+ bkey_reassemble(&new.k, k);
+ bch_cut_front(iter.pos, &new.k);
+ bch_cut_back(insert->k.p, &new.k.k);
+ e = bkey_i_to_s_extent(&new.k);
+
+ ptr = bch_migrate_matching_ptr(io, e);
+ if (ptr) {
+ if (io->move)
+ __bch_extent_drop_ptr(e, ptr);
+
+ memcpy(extent_entry_last(e),
+ &insert->v,
+ bkey_val_bytes(&insert->k));
+ e.k->u64s += bkey_val_u64s(&insert->k);
+
+ bch_extent_narrow_crcs(e);
+ bch_extent_drop_redundant_crcs(e);
+ bch_extent_normalize(c, e.s);
+
+ ret = bch_btree_insert_at(c, &op->res,
+ NULL, op_journal_seq(op),
+ BTREE_INSERT_NOFAIL|BTREE_INSERT_ATOMIC,
+ BTREE_INSERT_ENTRY(&iter, &new.k));
+ if (ret && ret != -EINTR)
+ break;
+ } else {
+nomatch:
+ bch_btree_iter_set_pos(&iter, k.k->p);
+ }
+
+ while (bkey_cmp(iter.pos, bch_keylist_front(keys)->k.p) >= 0) {
+ bch_keylist_dequeue(keys);
+ if (bch_keylist_empty(keys))
+ goto out;
+ }
+
+ bch_cut_front(iter.pos, bch_keylist_front(keys));
+ }
+out:
+ bch_btree_iter_unlock(&iter);
+ return ret;
+}
+
static void moving_error(struct moving_context *ctxt, unsigned flag)
{
atomic_inc(&ctxt->error_count);
@@ -86,7 +194,11 @@ static void moving_init(struct moving_io *io, struct bio *bio)
bch_bio_map(bio, NULL);
}
-struct moving_io *moving_io_alloc(struct bkey_s_c k)
+struct moving_io *moving_io_alloc(struct cache_set *c,
+ struct moving_queue *q,
+ struct write_point *wp,
+ struct bkey_s_c k,
+ const struct bch_extent_ptr *move_ptr)
{
struct moving_io *io;
@@ -105,6 +217,26 @@ struct moving_io *moving_io_alloc(struct bkey_s_c k)
return NULL;
}
+ bch_write_op_init(&io->op, c, &io->wbio,
+ (struct disk_reservation) { 0 },
+ wp,
+ bkey_to_s_c(&KEY(k.k->p.inode,
+ k.k->p.offset,
+ k.k->size)),
+ NULL, NULL,
+ bkey_extent_is_cached(k.k)
+ ? BCH_WRITE_CACHED : 0);
+
+ io->op.io_wq = q->wq;
+ io->op.nr_replicas = 1;
+ io->op.index_update_fn = bch_migrate_index_update;
+
+ if (move_ptr) {
+ io->move_ptr = *move_ptr;
+ io->move = true;
+ io->sort_key = move_ptr->offset;
+ }
+
return io;
}
@@ -122,8 +254,8 @@ static void moving_io_destructor(struct closure *cl)
unsigned long flags;
bool kick_writes = true;
- if (io->replace.failures)
- trace_bcache_copy_collision(q, &io->key.k);
+ //if (io->replace.failures)
+ // trace_bcache_copy_collision(q, &io->key.k);
spin_lock_irqsave(&q->lock, flags);
diff --git a/drivers/md/bcache/move.h b/drivers/md/bcache/move.h
index 2f9998e66e7f..bdf5aaec8a50 100644
--- a/drivers/md/bcache/move.h
+++ b/drivers/md/bcache/move.h
@@ -66,9 +66,10 @@ struct moving_io {
struct rb_node node;
struct closure cl;
struct moving_queue *q;
- struct bch_write_op op;
- struct bch_replace_info replace;
struct moving_context *context;
+ struct bch_write_op op;
+ struct bch_extent_ptr move_ptr;
+ bool move;
BKEY_PADDED(key);
/* Sort key for moving_queue->tree */
u64 sort_key;
@@ -99,8 +100,12 @@ struct moving_io {
struct bio_vec bi_inline_vecs[0];
};
-struct moving_io *moving_io_alloc(struct bkey_s_c);
void moving_io_free(struct moving_io *);
+struct moving_io *moving_io_alloc(struct cache_set *,
+ struct moving_queue *,
+ struct write_point *,
+ struct bkey_s_c,
+ const struct bch_extent_ptr *);
typedef struct moving_io *(moving_queue_fn)(struct moving_queue *,
struct moving_context *);
diff --git a/drivers/md/bcache/movinggc.c b/drivers/md/bcache/movinggc.c
index 22f6fb8dd212..a18340031368 100644
--- a/drivers/md/bcache/movinggc.c
+++ b/drivers/md/bcache/movinggc.c
@@ -43,49 +43,32 @@ static bool moving_pred(struct scan_keylist *kl, struct bkey_s_c k)
static int issue_moving_gc_move(struct moving_queue *q,
struct moving_context *ctxt,
- struct bkey_i *k)
+ struct bkey_s_c k)
{
struct cache *ca = container_of(q, struct cache, moving_gc_queue);
struct cache_set *c = ca->set;
- struct bkey_s_extent e;
- struct bch_extent_ptr *ptr;
+ const struct bch_extent_ptr *ptr;
struct moving_io *io;
unsigned gen;
- io = moving_io_alloc(bkey_i_to_s_c(k));
- if (!io) {
- trace_bcache_moving_gc_alloc_fail(c, k->k.size);
- return -ENOMEM;
- }
-
- bch_replace_init(&io->replace, bkey_i_to_s_c(k));
-
- bch_write_op_init(&io->op, c, &io->wbio,
- (struct disk_reservation) { 0 },
- NULL, bkey_i_to_s_c(k),
- &io->replace.hook, NULL,
- bkey_extent_is_cached(&k->k)
- ? BCH_WRITE_CACHED : 0);
- io->op.nr_replicas = 1;
-
- e = bkey_i_to_s_extent(&io->op.insert_key);
-
- extent_for_each_ptr(e, ptr)
+ extent_for_each_ptr(bkey_s_c_to_extent(k), ptr)
if ((ca->sb.nr_this_dev == ptr->dev) &&
- (gen = PTR_BUCKET(ca, ptr)->copygc_gen)) {
- gen--;
- BUG_ON(gen > ARRAY_SIZE(ca->gc_buckets));
- io->op.wp = &ca->gc_buckets[gen];
- io->sort_key = ptr->offset;
- bch_extent_drop_ptr(e, ptr);
+ (gen = PTR_BUCKET(ca, ptr)->copygc_gen))
goto found;
- }
/* We raced - bucket's been reused */
- moving_io_free(io);
goto out;
found:
- trace_bcache_gc_copy(&k->k);
+ gen--;
+ BUG_ON(gen > ARRAY_SIZE(ca->gc_buckets));
+
+ io = moving_io_alloc(c, q, &ca->gc_buckets[gen], k, ptr);
+ if (!io) {
+ trace_bcache_moving_gc_alloc_fail(c, k.k->size);
+ return -ENOMEM;
+ }
+
+ trace_bcache_gc_copy(k.k);
/*
* IMPORTANT: We must call bch_data_move before we dequeue so
@@ -133,7 +116,7 @@ static void read_moving(struct cache *ca, struct moving_context *ctxt)
break;
if (issue_moving_gc_move(&ca->moving_gc_queue,
- ctxt, k)) {
+ ctxt, bkey_i_to_s_c(k))) {
/*
* Memory allocation failed; we will wait for
* all queued moves to finish and continue
diff --git a/drivers/md/bcache/tier.c b/drivers/md/bcache/tier.c
index caf6b3df2c9c..a68726fedd5c 100644
--- a/drivers/md/bcache/tier.c
+++ b/drivers/md/bcache/tier.c
@@ -214,22 +214,12 @@ static int issue_tiering_move(struct moving_queue *q,
struct cache_set *c = ca->set;
struct moving_io *io;
- io = moving_io_alloc(k);
+ io = moving_io_alloc(c, q, &ca->tiering_write_point, k, NULL);
if (!io) {
trace_bcache_tiering_alloc_fail(c, k.k->size);
return -ENOMEM;
}
- bch_replace_init(&io->replace, bkey_i_to_s_c(&io->key));
-
- bch_write_op_init(&io->op, c, &io->wbio,
- (struct disk_reservation) { 0 },
- &ca->tiering_write_point,
- bkey_i_to_s_c(&io->key),
- &io->replace.hook, NULL, 0);
- io->op.io_wq = q->wq;
- io->op.nr_replicas = 1;
-
trace_bcache_tiering_copy(k.k);
/*