Commit 19393e10 authored by Philipp Reisner's avatar Philipp Reisner

drbd: Converted drbd_worker() from mdev to tconn

Signed-off-by: default avatarPhilipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: default avatarLars Ellenberg <lars.ellenberg@linbit.com>
parent 32862ec7
...@@ -1624,35 +1624,53 @@ void drbd_start_resync(struct drbd_conf *mdev, enum drbd_conns side) ...@@ -1624,35 +1624,53 @@ void drbd_start_resync(struct drbd_conf *mdev, enum drbd_conns side)
drbd_state_unlock(mdev); 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) 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; struct drbd_work *w = NULL;
LIST_HEAD(work_list); LIST_HEAD(work_list);
int intr = 0, i; int intr = 0;
while (get_t_state(thi) == RUNNING) { while (get_t_state(thi) == RUNNING) {
drbd_thread_current_set_cpu(thi); drbd_thread_current_set_cpu(thi);
if (down_trylock(&mdev->tconn->data.work.s)) { if (down_trylock(&tconn->data.work.s)) {
mutex_lock(&mdev->tconn->data.mutex); mutex_lock(&tconn->data.mutex);
if (mdev->tconn->data.socket && !mdev->tconn->net_conf->no_cork) if (tconn->data.socket && !tconn->net_conf->no_cork)
drbd_tcp_uncork(mdev->tconn->data.socket); drbd_tcp_uncork(tconn->data.socket);
mutex_unlock(&mdev->tconn->data.mutex); 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); mutex_lock(&tconn->data.mutex);
if (mdev->tconn->data.socket && !mdev->tconn->net_conf->no_cork) if (tconn->data.socket && !tconn->net_conf->no_cork)
drbd_tcp_cork(mdev->tconn->data.socket); drbd_tcp_cork(tconn->data.socket);
mutex_unlock(&mdev->tconn->data.mutex); mutex_unlock(&tconn->data.mutex);
} }
if (intr) { if (intr) {
D_ASSERT(intr == -EINTR);
flush_signals(current); 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; continue;
}
break; break;
} }
...@@ -1663,8 +1681,8 @@ int drbd_worker(struct drbd_thread *thi) ...@@ -1663,8 +1681,8 @@ int drbd_worker(struct drbd_thread *thi)
this... */ this... */
w = NULL; w = NULL;
spin_lock_irq(&mdev->tconn->data.work.q_lock); spin_lock_irq(&tconn->data.work.q_lock);
if (!expect(!list_empty(&mdev->tconn->data.work.q))) { if (list_empty(&tconn->data.work.q)) {
/* something terribly wrong in our logic. /* something terribly wrong in our logic.
* we were able to down() the semaphore, * we were able to down() the semaphore,
* but the list is empty... doh. * but the list is empty... doh.
...@@ -1676,57 +1694,44 @@ int drbd_worker(struct drbd_thread *thi) ...@@ -1676,57 +1694,44 @@ int drbd_worker(struct drbd_thread *thi)
* *
* I'll try to get away just starting over this loop. * 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; 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); 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"); */ /* dev_warn(DEV, "worker: a callback failed! \n"); */
if (mdev->state.conn >= C_CONNECTED) if (tconn->volume0->state.conn >= C_CONNECTED)
drbd_force_state(mdev, drbd_force_state(tconn->volume0,
NS(conn, C_NETWORK_FAILURE)); 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); spin_lock_irq(&tconn->data.work.q_lock);
i = 0; while (!list_empty(&tconn->data.work.q)) {
while (!list_empty(&mdev->tconn->data.work.q)) { list_splice_init(&tconn->data.work.q, &work_list);
list_splice_init(&mdev->tconn->data.work.q, &work_list); spin_unlock_irq(&tconn->data.work.q_lock);
spin_unlock_irq(&mdev->tconn->data.work.q_lock);
while (!list_empty(&work_list)) { while (!list_empty(&work_list)) {
w = list_entry(work_list.next, struct drbd_work, list); w = list_entry(work_list.next, struct drbd_work, list);
list_del_init(&w->list); list_del_init(&w->list);
w->cb(mdev, w, 1); w->cb(w->mdev, w, 1);
i++; /* dead debugging code */
} }
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, /* DANGEROUS race: if someone did queue his work within the spinlock,
* but up() ed outside the spinlock, we could get an up() on the * but up() ed outside the spinlock, we could get an up() on the
* semaphore without corresponding list entry. * semaphore without corresponding list entry.
* So don't do that. * 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); idr_for_each(&tconn->volumes, _worker_dying, NULL);
/* _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);
return 0; return 0;
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment