summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2016-05-02 23:57:40 -0800
committerKent Overstreet <kent.overstreet@gmail.com>2016-10-07 12:36:26 -0800
commitab4f27b48e6b592eb3b962ee300840226ec91b5f (patch)
tree514da21065eef7207ed229f630dbd1490d79269e
parent5a48df1974fbf518bb48fe26ea3284059de27b5e (diff)
bcache: fix moving queue init for runtime device add
-rw-r--r--drivers/md/bcache/keylist.c8
-rw-r--r--drivers/md/bcache/migrate.c4
-rw-r--r--drivers/md/bcache/move.c47
-rw-r--r--drivers/md/bcache/move.h18
-rw-r--r--drivers/md/bcache/move_types.h3
-rw-r--r--drivers/md/bcache/movinggc.c24
-rw-r--r--drivers/md/bcache/movinggc.h2
-rw-r--r--drivers/md/bcache/super.c38
-rw-r--r--drivers/md/bcache/tier.c23
-rw-r--r--drivers/md/bcache/tier.h4
10 files changed, 82 insertions, 89 deletions
diff --git a/drivers/md/bcache/keylist.c b/drivers/md/bcache/keylist.c
index d98a1c83382a..638596300575 100644
--- a/drivers/md/bcache/keylist.c
+++ b/drivers/md/bcache/keylist.c
@@ -145,9 +145,11 @@ void bch_scan_keylist_init(struct scan_keylist *kl,
void bch_scan_keylist_destroy(struct scan_keylist *kl)
{
- mutex_lock(&kl->c->gc_scan_keylist_lock);
- list_del(&kl->mark_list);
- mutex_unlock(&kl->c->gc_scan_keylist_lock);
+ if (kl->c) {
+ mutex_lock(&kl->c->gc_scan_keylist_lock);
+ list_del(&kl->mark_list);
+ mutex_unlock(&kl->c->gc_scan_keylist_lock);
+ }
mutex_lock(&kl->lock);
bch_keylist_free(&kl->list);
diff --git a/drivers/md/bcache/migrate.c b/drivers/md/bcache/migrate.c
index 213fb0ed754f..30d78457c6bc 100644
--- a/drivers/md/bcache/migrate.c
+++ b/drivers/md/bcache/migrate.c
@@ -128,9 +128,7 @@ int bch_move_data_off_device(struct cache *ca)
* devices).
*/
- ret = bch_queue_start(queue, "bch_move_data_off_device");
- if (ret)
- return ret;
+ bch_queue_start(queue);
queue_io_resize(queue, MIGRATE_NR, MIGRATE_READ_NR, MIGRATE_WRITE_NR);
diff --git a/drivers/md/bcache/move.c b/drivers/md/bcache/move.c
index 19d8faf271fe..a2c1d85f0127 100644
--- a/drivers/md/bcache/move.c
+++ b/drivers/md/bcache/move.c
@@ -252,19 +252,16 @@ static void bch_queue_write_work(struct work_struct *work)
* allocates it.
*/
-void bch_queue_init(struct moving_queue *q,
- struct cache_set *c,
- unsigned max_size,
- unsigned max_count,
- unsigned max_read_count,
- unsigned max_write_count,
- bool rotational)
+int bch_queue_init(struct moving_queue *q,
+ struct cache_set *c,
+ unsigned max_size,
+ unsigned max_count,
+ unsigned max_read_count,
+ unsigned max_write_count,
+ bool rotational,
+ const char *name)
{
- if (test_and_set_bit(MOVING_QUEUE_INITIALIZED, &q->flags))
- return;
-
INIT_WORK(&q->work, bch_queue_write_work);
- bch_scan_keylist_init(&q->keys, c, max_size);
q->keys.owner = q;
q->max_count = max_count;
@@ -276,10 +273,16 @@ void bch_queue_init(struct moving_queue *q,
INIT_LIST_HEAD(&q->pending);
INIT_LIST_HEAD(&q->write_pending);
q->tree = RB_ROOT;
+
+ q->wq = alloc_workqueue(name,
+ WQ_UNBOUND|WQ_FREEZABLE|WQ_MEM_RECLAIM, 1);
+ if (!q->wq)
+ return -ENOMEM;
+
+ return 0;
}
-int bch_queue_start(struct moving_queue *q,
- const char *name)
+void bch_queue_start(struct moving_queue *q)
{
unsigned long flags;
@@ -288,16 +291,6 @@ int bch_queue_start(struct moving_queue *q,
spin_unlock_irqrestore(&q->lock, flags);
bch_scan_keylist_reset(&q->keys);
-
- /* Re-use workqueue if already started */
- if (!q->wq)
- q->wq = alloc_workqueue(name,
- WQ_UNBOUND|WQ_FREEZABLE|WQ_MEM_RECLAIM, 1);
-
- if (!q->wq)
- return -ENOMEM;
-
- return 0;
}
void queue_io_resize(struct moving_queue *q,
@@ -316,13 +309,9 @@ void queue_io_resize(struct moving_queue *q,
void bch_queue_destroy(struct moving_queue *q)
{
- if (!test_and_clear_bit(MOVING_QUEUE_INITIALIZED, &q->flags))
- return;
-
- if (q->wq) {
+ if (q->wq)
destroy_workqueue(q->wq);
- q->wq = NULL;
- }
+ q->wq = NULL;
bch_scan_keylist_destroy(&q->keys);
}
diff --git a/drivers/md/bcache/move.h b/drivers/md/bcache/move.h
index 8ce99204a264..2f9998e66e7f 100644
--- a/drivers/md/bcache/move.h
+++ b/drivers/md/bcache/move.h
@@ -105,15 +105,15 @@ void moving_io_free(struct moving_io *);
typedef struct moving_io *(moving_queue_fn)(struct moving_queue *,
struct moving_context *);
-void bch_queue_init(struct moving_queue *,
- struct cache_set *,
- unsigned max_keys,
- unsigned max_ios,
- unsigned max_reads,
- unsigned max_writes,
- bool rotational);
-int bch_queue_start(struct moving_queue *,
- const char *);
+int bch_queue_init(struct moving_queue *,
+ struct cache_set *,
+ unsigned max_keys,
+ unsigned max_ios,
+ unsigned max_reads,
+ unsigned max_writes,
+ bool rotational,
+ const char *);
+void bch_queue_start(struct moving_queue *);
bool bch_queue_full(struct moving_queue *);
void bch_data_move(struct moving_queue *,
struct moving_context *,
diff --git a/drivers/md/bcache/move_types.h b/drivers/md/bcache/move_types.h
index cca49d5782ba..d5e1a4a968fa 100644
--- a/drivers/md/bcache/move_types.h
+++ b/drivers/md/bcache/move_types.h
@@ -1,15 +1,12 @@
#ifndef _BCACHE_MOVE_TYPES_H
#define _BCACHE_MOVE_TYPES_H
-#define MOVING_QUEUE_INITIALIZED 1
-
/*
* We rely on moving_queue being kzalloc'd so that the initial value of
* the flags is 0.
*/
struct moving_queue {
- unsigned long flags;
struct work_struct work;
struct scan_keylist keys;
struct workqueue_struct *wq;
diff --git a/drivers/md/bcache/movinggc.c b/drivers/md/bcache/movinggc.c
index 01987bf7bdf5..2f5f59ba6177 100644
--- a/drivers/md/bcache/movinggc.c
+++ b/drivers/md/bcache/movinggc.c
@@ -311,33 +311,31 @@ static int bch_moving_gc_thread(void *arg)
#define MOVING_GC_READ_NR 32
#define MOVING_GC_WRITE_NR 32
-void bch_moving_init_cache(struct cache *ca)
+int bch_moving_init_cache(struct cache *ca)
{
bool rotational = !blk_queue_nonrot(bdev_get_queue(ca->disk_sb.bdev));
bch_pd_controller_init(&ca->moving_gc_pd);
- bch_queue_init(&ca->moving_gc_queue,
- ca->set,
- MOVING_GC_KEYS_MAX_SIZE,
- MOVING_GC_NR,
- MOVING_GC_READ_NR,
- MOVING_GC_WRITE_NR,
- rotational);
ca->moving_gc_pd.d_term = 0;
+
+ return bch_queue_init(&ca->moving_gc_queue,
+ ca->set,
+ MOVING_GC_KEYS_MAX_SIZE,
+ MOVING_GC_NR,
+ MOVING_GC_READ_NR,
+ MOVING_GC_WRITE_NR,
+ rotational,
+ "bch_copygc_write");
}
int bch_moving_gc_thread_start(struct cache *ca)
{
struct task_struct *t;
- int ret;
/* The moving gc read thread must be stopped */
BUG_ON(ca->moving_gc_read != NULL);
- ret = bch_queue_start(&ca->moving_gc_queue,
- "bch_copygc_write");
- if (ret)
- return ret;
+ bch_queue_start(&ca->moving_gc_queue);
if (cache_set_init_fault("moving_gc_start"))
return -ENOMEM;
diff --git a/drivers/md/bcache/movinggc.h b/drivers/md/bcache/movinggc.h
index 9c35d7ef2782..5d09e0fa3ae1 100644
--- a/drivers/md/bcache/movinggc.h
+++ b/drivers/md/bcache/movinggc.h
@@ -1,7 +1,7 @@
#ifndef _BCACHE_MOVINGGC_H
#define _BCACHE_MOVINGGC_H
-void bch_moving_init_cache(struct cache *);
+int bch_moving_init_cache(struct cache *);
void bch_moving_gc_stop(struct cache *);
int bch_moving_gc_thread_start(struct cache *);
void bch_moving_gc_destroy(struct cache *);
diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c
index 2b934e67a944..8803994bf992 100644
--- a/drivers/md/bcache/super.c
+++ b/drivers/md/bcache/super.c
@@ -850,9 +850,7 @@ static const char *__bch_cache_set_read_write(struct cache_set *c)
goto err;
}
- err = "error starting tiering write workqueue";
- if (bch_tiering_write_start(ca))
- return err;
+ bch_tiering_write_start(ca);
}
err = "error starting tiering thread";
@@ -1569,11 +1567,7 @@ static const char *__bch_cache_read_write(struct cache *ca)
trace_bcache_cache_read_write(ca);
- if (bch_cache_allocator_start(ca))
- return "error starting allocator thread";
-
- if (bch_tiering_write_start(ca))
- return "error starting tiering write workqueue";
+ bch_tiering_write_start(ca);
trace_bcache_cache_read_write_done(ca);
@@ -1604,6 +1598,9 @@ const char *bch_cache_read_write(struct cache *ca)
if (test_bit(CACHE_DEV_REMOVING, &ca->flags))
return "removing";
+ if (bch_cache_allocator_start(ca))
+ return "error starting allocator thread";
+
err = __bch_cache_read_write(ca);
if (err)
return err;
@@ -1950,7 +1947,9 @@ static const char *cache_alloc(struct bcache_superblock *sb,
!(ca->bio_prio = bio_kmalloc(GFP_NOIO, bucket_pages(ca))) ||
bioset_init(&ca->replica_set, 4,
offsetof(struct bch_write_bio, bio.bio)) ||
- !(ca->sectors_written = alloc_percpu(*ca->sectors_written)))
+ !(ca->sectors_written = alloc_percpu(*ca->sectors_written)) ||
+ bch_moving_init_cache(ca) ||
+ bch_tiering_init_cache(ca))
goto err;
ca->prio_last_buckets = ca->prio_buckets + prio_buckets(ca);
@@ -1968,15 +1967,18 @@ static const char *cache_alloc(struct bcache_superblock *sb,
ca->tiering_write_point.reserve = RESERVE_NONE;
ca->tiering_write_point.group = &ca->self;
+ /* XXX: scan keylists will die */
+ bch_scan_keylist_init(&ca->moving_gc_queue.keys, c,
+ DFLT_SCAN_KEYLIST_MAX_SIZE);
+ bch_scan_keylist_init(&ca->tiering_queue.keys, c,
+ DFLT_SCAN_KEYLIST_MAX_SIZE);
+
kobject_get(&c->kobj);
ca->set = c;
kobject_get(&ca->kobj);
rcu_assign_pointer(c->cache[ca->sb.nr_this_dev], ca);
- bch_moving_init_cache(ca);
- bch_tiering_init_cache(ca);
-
if (le64_to_cpu(ca->disk_sb.sb->seq) > le64_to_cpu(c->disk_sb.seq))
cache_sb_to_cache_set(c, ca->disk_sb.sb);
@@ -2164,9 +2166,15 @@ have_slot:
bch_notify_cache_added(ca);
- err = __bch_cache_read_write(ca);
- if (err)
- goto err_put;
+ if (ca->mi.state == CACHE_ACTIVE) {
+ err = bch_cache_allocator_start_once(ca);
+ if (err)
+ goto err_put;
+
+ err = __bch_cache_read_write(ca);
+ if (err)
+ goto err_put;
+ }
kobject_put(&ca->kobj);
mutex_unlock(&bch_register_lock);
diff --git a/drivers/md/bcache/tier.c b/drivers/md/bcache/tier.c
index 53653f6ea478..caf6b3df2c9c 100644
--- a/drivers/md/bcache/tier.c
+++ b/drivers/md/bcache/tier.c
@@ -408,22 +408,23 @@ void bch_tiering_init_cache_set(struct cache_set *c)
bch_pd_controller_init(&c->tiering_pd);
}
-void bch_tiering_init_cache(struct cache *ca)
+int bch_tiering_init_cache(struct cache *ca)
{
- bch_queue_init(&ca->tiering_queue,
- ca->set,
- TIERING_KEYS_MAX_SIZE,
- TIERING_NR,
- TIERING_READ_NR,
- TIERING_WRITE_NR,
- false);
-
ca->tiering_stripe_size = ca->mi.bucket_size * 2;
+
+ return bch_queue_init(&ca->tiering_queue,
+ ca->set,
+ TIERING_KEYS_MAX_SIZE,
+ TIERING_NR,
+ TIERING_READ_NR,
+ TIERING_WRITE_NR,
+ false,
+ "bch_tier_write");
}
-int bch_tiering_write_start(struct cache *ca)
+void bch_tiering_write_start(struct cache *ca)
{
- return bch_queue_start(&ca->tiering_queue, "bch_tier_write");
+ bch_queue_start(&ca->tiering_queue);
}
int bch_tiering_read_start(struct cache_set *c)
diff --git a/drivers/md/bcache/tier.h b/drivers/md/bcache/tier.h
index e9e810f2a865..57b4acf86fb5 100644
--- a/drivers/md/bcache/tier.h
+++ b/drivers/md/bcache/tier.h
@@ -2,9 +2,9 @@
#define _BCACHE_TIER_H
void bch_tiering_init_cache_set(struct cache_set *);
-void bch_tiering_init_cache(struct cache *);
+int bch_tiering_init_cache(struct cache *);
int bch_tiering_read_start(struct cache_set *);
-int bch_tiering_write_start(struct cache *);
+void bch_tiering_write_start(struct cache *);
void bch_tiering_write_destroy(struct cache *);
void bch_tiering_write_stop(struct cache *);
void bch_tiering_read_stop(struct cache_set *);