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);
/* 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(). */
/* 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);
retcode = ERR_CONN_IN_USE;
drbd_msg_put_info("failed to delete connection");
}
-
up_write(&drbd_cfg_rwsem);
goto out;
out_unlock:
}
up_write(&drbd_cfg_rwsem);
+ if (retcode == NO_ERROR)
+ drbd_thread_stop(&adm_ctx.tconn->worker);
out:
drbd_adm_finish(info, retcode);
return 0;
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);
resume_next_sg(mdev);
}
- after_all_state_ch(mdev->tconn);
-
drbd_md_sync(mdev);
}
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 =
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;
}
*/
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);