diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2016-05-02 23:57:40 -0800 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@gmail.com> | 2016-10-07 12:36:26 -0800 |
commit | ab4f27b48e6b592eb3b962ee300840226ec91b5f (patch) | |
tree | 514da21065eef7207ed229f630dbd1490d79269e | |
parent | 5a48df1974fbf518bb48fe26ea3284059de27b5e (diff) |
bcache: fix moving queue init for runtime device add
-rw-r--r-- | drivers/md/bcache/keylist.c | 8 | ||||
-rw-r--r-- | drivers/md/bcache/migrate.c | 4 | ||||
-rw-r--r-- | drivers/md/bcache/move.c | 47 | ||||
-rw-r--r-- | drivers/md/bcache/move.h | 18 | ||||
-rw-r--r-- | drivers/md/bcache/move_types.h | 3 | ||||
-rw-r--r-- | drivers/md/bcache/movinggc.c | 24 | ||||
-rw-r--r-- | drivers/md/bcache/movinggc.h | 2 | ||||
-rw-r--r-- | drivers/md/bcache/super.c | 38 | ||||
-rw-r--r-- | drivers/md/bcache/tier.c | 23 | ||||
-rw-r--r-- | drivers/md/bcache/tier.h | 4 |
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 *); |