diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index a5c9b385223af994d3ef90125d020f3a12589ebf..427e959e4869484e88a1a61cb5fe799aa4ff1ef9 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -503,7 +503,7 @@ static int drbd_thread_setup(void *arg) thi->task = NULL; thi->t_state = NONE; smp_mb(); - complete(&thi->stop); + complete_all(&thi->stop); spin_unlock_irqrestore(&thi->t_lock, flags); conn_info(tconn, "Terminating %s\n", current->comm); diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c index 9d9b93f0885012fcea0ae1f476776d5a01b8431d..25468e2be8d03081734b9e9fdac8f17784b3aa01 100644 --- a/drivers/block/drbd/drbd_nl.c +++ b/drivers/block/drbd/drbd_nl.c @@ -1050,10 +1050,16 @@ static void conn_reconfig_start(struct drbd_tconn *tconn) /* if still unconfigured, stops worker again. */ static void conn_reconfig_done(struct drbd_tconn *tconn) { + bool stop_threads; spin_lock_irq(&tconn->req_lock); - if (conn_all_vols_unconf(tconn)) - drbd_thread_stop_nowait(&tconn->worker); + stop_threads = conn_all_vols_unconf(tconn); spin_unlock_irq(&tconn->req_lock); + if (stop_threads) { + /* asender is implicitly stopped by receiver + * in drbd_disconnect() */ + drbd_thread_stop(&tconn->receiver); + drbd_thread_stop(&tconn->worker); + } } /* Make sure IO is suspended before calling this function(). */ @@ -3123,7 +3129,6 @@ int drbd_adm_down(struct sk_buff *skb, struct genl_info *info) /* delete connection */ if (conn_lowest_minor(adm_ctx.tconn) < 0) { - drbd_thread_stop(&adm_ctx.tconn->worker); list_del(&adm_ctx.tconn->all_tconn); kref_put(&adm_ctx.tconn->kref, &conn_destroy); @@ -3133,7 +3138,6 @@ int drbd_adm_down(struct sk_buff *skb, struct genl_info *info) retcode = ERR_CONN_IN_USE; drbd_msg_put_info("failed to delete connection"); } - up_write(&drbd_cfg_rwsem); goto out; out_unlock: @@ -3164,6 +3168,8 @@ int drbd_adm_delete_connection(struct sk_buff *skb, struct genl_info *info) } up_write(&drbd_cfg_rwsem); + if (retcode == NO_ERROR) + drbd_thread_stop(&adm_ctx.tconn->worker); out: drbd_adm_finish(info, retcode); return 0; diff --git a/drivers/block/drbd/drbd_state.c b/drivers/block/drbd/drbd_state.c index 0512bbb952e8229250345c608099fe8b55a4b345..523ec0940673a4477447548e9ee136fa239ed7ea 100644 --- a/drivers/block/drbd/drbd_state.c +++ b/drivers/block/drbd/drbd_state.c @@ -40,7 +40,6 @@ struct after_state_chg_work { static int w_after_state_ch(struct drbd_work *w, int unused); static void after_state_ch(struct drbd_conf *mdev, union drbd_state os, union drbd_state ns, enum chg_state_flags flags); -static void after_all_state_ch(struct drbd_tconn *tconn); static enum drbd_state_rv is_valid_state(struct drbd_conf *, union drbd_state); static enum drbd_state_rv is_valid_soft_transition(union drbd_state, union drbd_state); static enum drbd_state_rv is_valid_transition(union drbd_state os, union drbd_state ns); @@ -1380,8 +1379,6 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os, resume_next_sg(mdev); } - after_all_state_ch(mdev->tconn); - drbd_md_sync(mdev); } @@ -1393,12 +1390,6 @@ struct after_conn_state_chg_work { enum chg_state_flags flags; }; -static void after_all_state_ch(struct drbd_tconn *tconn) -{ - if (conn_all_vols_unconf(tconn)) - drbd_thread_stop_nowait(&tconn->worker); -} - static int w_after_conn_state_ch(struct drbd_work *w, int unused) { struct after_conn_state_chg_work *acscw = @@ -1461,12 +1452,7 @@ static int w_after_conn_state_ch(struct drbd_work *w, int unused) spin_unlock_irq(&tconn->req_lock); } } - - - //conn_err(tconn, STATE_FMT, STATE_ARGS("nms", nms)); - after_all_state_ch(tconn); kref_put(&tconn->kref, &conn_destroy); - return 0; } diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c index 7a73bd4287c411bed3abe7e2a81bd9a9391d57c4..0da1547bb2d25ba2a51a279f340edf6f6e90cc37 100644 --- a/drivers/block/drbd/drbd_worker.c +++ b/drivers/block/drbd/drbd_worker.c @@ -1744,10 +1744,6 @@ int drbd_worker(struct drbd_thread *thi) */ spin_unlock_irq(&tconn->data.work.q_lock); - /* _drbd_set_state only uses stop_nowait. - * wait here for the exiting receiver. */ - drbd_thread_stop(&tconn->receiver); - down_read(&drbd_cfg_rwsem); idr_for_each_entry(&tconn->volumes, mdev, vnr) { D_ASSERT(mdev->state.disk == D_DISKLESS && mdev->state.conn == C_STANDALONE);