drbd_state_unlock(mdev);
}
+static int _worker_dying(int vnr, void *p, void *data)
+{
+ struct drbd_conf *mdev = (struct drbd_conf *)p;
+
+ D_ASSERT(mdev->state.disk == D_DISKLESS && mdev->state.conn == C_STANDALONE);
+ /* _drbd_set_state only uses stop_nowait.
+ * wait here for the exiting receiver. */
+ drbd_thread_stop(&mdev->tconn->receiver);
+ drbd_mdev_cleanup(mdev);
+
+ clear_bit(DEVICE_DYING, &mdev->flags);
+ clear_bit(CONFIG_PENDING, &mdev->flags);
+ wake_up(&mdev->state_wait);
+
+ return 0;
+}
+
int drbd_worker(struct drbd_thread *thi)
{
- struct drbd_conf *mdev = thi->mdev;
+ struct drbd_tconn *tconn = thi->mdev->tconn;
struct drbd_work *w = NULL;
LIST_HEAD(work_list);
- int intr = 0, i;
+ int intr = 0;
while (get_t_state(thi) == RUNNING) {
drbd_thread_current_set_cpu(thi);
- if (down_trylock(&mdev->tconn->data.work.s)) {
- mutex_lock(&mdev->tconn->data.mutex);
- if (mdev->tconn->data.socket && !mdev->tconn->net_conf->no_cork)
- drbd_tcp_uncork(mdev->tconn->data.socket);
- mutex_unlock(&mdev->tconn->data.mutex);
+ if (down_trylock(&tconn->data.work.s)) {
+ mutex_lock(&tconn->data.mutex);
+ if (tconn->data.socket && !tconn->net_conf->no_cork)
+ drbd_tcp_uncork(tconn->data.socket);
+ mutex_unlock(&tconn->data.mutex);
- intr = down_interruptible(&mdev->tconn->data.work.s);
+ intr = down_interruptible(&tconn->data.work.s);
- mutex_lock(&mdev->tconn->data.mutex);
- if (mdev->tconn->data.socket && !mdev->tconn->net_conf->no_cork)
- drbd_tcp_cork(mdev->tconn->data.socket);
- mutex_unlock(&mdev->tconn->data.mutex);
+ mutex_lock(&tconn->data.mutex);
+ if (tconn->data.socket && !tconn->net_conf->no_cork)
+ drbd_tcp_cork(tconn->data.socket);
+ mutex_unlock(&tconn->data.mutex);
}
if (intr) {
- D_ASSERT(intr == -EINTR);
flush_signals(current);
- if (!expect(get_t_state(thi) != RUNNING))
+ if (get_t_state(thi) == RUNNING) {
+ conn_warn(tconn, "Worker got an unexpected signal\n");
continue;
+ }
break;
}
this... */
w = NULL;
- spin_lock_irq(&mdev->tconn->data.work.q_lock);
- if (!expect(!list_empty(&mdev->tconn->data.work.q))) {
+ spin_lock_irq(&tconn->data.work.q_lock);
+ if (list_empty(&tconn->data.work.q)) {
/* something terribly wrong in our logic.
* we were able to down() the semaphore,
* but the list is empty... doh.
*
* I'll try to get away just starting over this loop.
*/
- spin_unlock_irq(&mdev->tconn->data.work.q_lock);
+ conn_warn(tconn, "Work list unexpectedly empty\n");
+ spin_unlock_irq(&tconn->data.work.q_lock);
continue;
}
- w = list_entry(mdev->tconn->data.work.q.next, struct drbd_work, list);
+ w = list_entry(tconn->data.work.q.next, struct drbd_work, list);
list_del_init(&w->list);
- spin_unlock_irq(&mdev->tconn->data.work.q_lock);
+ spin_unlock_irq(&tconn->data.work.q_lock);
- if (!w->cb(mdev, w, mdev->state.conn < C_CONNECTED)) {
+ if (!w->cb(w->mdev, w, tconn->volume0->state.conn < C_CONNECTED)) {
/* dev_warn(DEV, "worker: a callback failed! \n"); */
- if (mdev->state.conn >= C_CONNECTED)
- drbd_force_state(mdev,
- NS(conn, C_NETWORK_FAILURE));
+ if (tconn->volume0->state.conn >= C_CONNECTED)
+ drbd_force_state(tconn->volume0,
+ NS(conn, C_NETWORK_FAILURE));
}
}
- D_ASSERT(test_bit(DEVICE_DYING, &mdev->flags));
- D_ASSERT(test_bit(CONFIG_PENDING, &mdev->flags));
- spin_lock_irq(&mdev->tconn->data.work.q_lock);
- i = 0;
- while (!list_empty(&mdev->tconn->data.work.q)) {
- list_splice_init(&mdev->tconn->data.work.q, &work_list);
- spin_unlock_irq(&mdev->tconn->data.work.q_lock);
+ spin_lock_irq(&tconn->data.work.q_lock);
+ while (!list_empty(&tconn->data.work.q)) {
+ list_splice_init(&tconn->data.work.q, &work_list);
+ spin_unlock_irq(&tconn->data.work.q_lock);
while (!list_empty(&work_list)) {
w = list_entry(work_list.next, struct drbd_work, list);
list_del_init(&w->list);
- w->cb(mdev, w, 1);
- i++; /* dead debugging code */
+ w->cb(w->mdev, w, 1);
}
- spin_lock_irq(&mdev->tconn->data.work.q_lock);
+ spin_lock_irq(&tconn->data.work.q_lock);
}
- sema_init(&mdev->tconn->data.work.s, 0);
+ sema_init(&tconn->data.work.s, 0);
/* DANGEROUS race: if someone did queue his work within the spinlock,
* but up() ed outside the spinlock, we could get an up() on the
* semaphore without corresponding list entry.
* So don't do that.
*/
- spin_unlock_irq(&mdev->tconn->data.work.q_lock);
+ spin_unlock_irq(&tconn->data.work.q_lock);
- D_ASSERT(mdev->state.disk == D_DISKLESS && mdev->state.conn == C_STANDALONE);
- /* _drbd_set_state only uses stop_nowait.
- * wait here for the exiting receiver. */
- drbd_thread_stop(&mdev->tconn->receiver);
- drbd_mdev_cleanup(mdev);
-
- dev_info(DEV, "worker terminated\n");
-
- clear_bit(DEVICE_DYING, &mdev->flags);
- clear_bit(CONFIG_PENDING, &mdev->flags);
- wake_up(&mdev->state_wait);
+ idr_for_each(&tconn->volumes, _worker_dying, NULL);
return 0;
}