From: ZouMingzhe <mingzhe.zou@xxxxxxxxxxxx> 1. bch_dirty_init_thread() dont check bch_root_node_dirty_init() error and return it, add result in struct dirty_init_thrd_info. 2. bch_sectors_dirty_init() dont check each thread result and return void, we should check each thread and return error. 3. bch_btree_check() and bch_sectors_dirty_init() must wait all threads stop, cannot return error immediately. Signed-off-by: Mingzhe Zou <mingzhe.zou@xxxxxxxxxxxx> --- drivers/md/bcache/btree.c | 6 +++++- drivers/md/bcache/writeback.c | 27 ++++++++++++++++++++++----- drivers/md/bcache/writeback.h | 3 ++- 3 files changed, 29 insertions(+), 7 deletions(-) diff --git a/drivers/md/bcache/btree.c b/drivers/md/bcache/btree.c index f8e6f5c7c736..f5f2718e03e5 100644 --- a/drivers/md/bcache/btree.c +++ b/drivers/md/bcache/btree.c @@ -2064,16 +2064,20 @@ int bch_btree_check(struct cache_set *c) for (--i; i >= 0; i--) kthread_stop(check_state->infos[i].thread); ret = -ENOMEM; - goto out; + goto out_wait; } } /* * Must wait for all threads to stop. */ +out_wait: wait_event_interruptible(check_state->wait, atomic_read(&check_state->started) == 0); + if (ret) + goto out; + for (i = 0; i < check_state->total_threads; i++) { if (check_state->infos[i].result) { ret = check_state->infos[i].result; diff --git a/drivers/md/bcache/writeback.c b/drivers/md/bcache/writeback.c index 5b828555bca8..f61cb71ca0c7 100644 --- a/drivers/md/bcache/writeback.c +++ b/drivers/md/bcache/writeback.c @@ -878,6 +878,7 @@ static int bch_root_node_dirty_init(struct cache_set *c, static int bch_dirty_init_thread(void *arg) { + int ret = 0; struct dirty_init_thrd_info *info = arg; struct bch_dirty_init_state *state = info->state; struct cache_set *c = state->c; @@ -919,7 +920,8 @@ static int bch_dirty_init_thread(void *arg) } if (p) { - if (bch_root_node_dirty_init(c, state->d, p) < 0) + ret = bch_root_node_dirty_init(c, state->d, p); + if (ret < 0) goto out; } @@ -929,6 +931,7 @@ static int bch_dirty_init_thread(void *arg) } out: + info->result = ret; /* In order to wake up state->wait in time */ smp_mb__before_atomic(); if (atomic_dec_and_test(&state->started)) @@ -949,8 +952,9 @@ static int bch_btre_dirty_init_thread_nr(void) return n; } -void bch_sectors_dirty_init(struct bcache_device *d) +int bch_sectors_dirty_init(struct bcache_device *d) { + int ret = 0; int i; struct bkey *k = NULL; struct btree_iter iter; @@ -969,13 +973,13 @@ void bch_sectors_dirty_init(struct bcache_device *d) for_each_key_filter(&c->root->keys, k, &iter, bch_ptr_invalid) sectors_dirty_init_fn(&op.op, c->root, k); - return; + return 0; } state = kzalloc(sizeof(struct bch_dirty_init_state), GFP_KERNEL); if (!state) { pr_warn("sectors dirty init failed: cannot allocate memory\n"); - return; + return -ENOMEM; } state->c = c; @@ -1005,18 +1009,31 @@ void bch_sectors_dirty_init(struct bcache_device *d) pr_err("fails to run thread bch_dirty_init[%d]\n", i); for (--i; i >= 0; i--) kthread_stop(state->infos[i].thread); - goto out; + ret = -ENOMEM; + goto out_wait; } } /* * Must wait for all threads to stop. */ +out_wait: wait_event_interruptible(state->wait, atomic_read(&state->started) == 0); + if (ret) + goto out; + + for (i = 0; i < state->total_threads; i++) { + if (state->infos[i].result) { + ret = state->infos[i].result; + goto out; + } + } + out: kfree(state); + return ret; } void bch_cached_dev_writeback_init(struct cached_dev *dc) diff --git a/drivers/md/bcache/writeback.h b/drivers/md/bcache/writeback.h index 02b2f9df73f6..0e42b3de5be6 100644 --- a/drivers/md/bcache/writeback.h +++ b/drivers/md/bcache/writeback.h @@ -32,6 +32,7 @@ struct bch_dirty_init_state; struct dirty_init_thrd_info { struct bch_dirty_init_state *state; struct task_struct *thread; + int result; }; struct bch_dirty_init_state { @@ -148,7 +149,7 @@ static inline void bch_writeback_add(struct cached_dev *dc) void bcache_dev_sectors_dirty_add(struct cache_set *c, unsigned int inode, uint64_t offset, int nr_sectors); -void bch_sectors_dirty_init(struct bcache_device *d); +int bch_sectors_dirty_init(struct bcache_device *d); void bch_cached_dev_writeback_init(struct cached_dev *dc); int bch_cached_dev_writeback_start(struct cached_dev *dc); -- 2.17.1