Loading drivers/block/drbd/drbd_worker.c +51 −46 Original line number Diff line number Diff line Loading @@ -1624,35 +1624,53 @@ void drbd_start_resync(struct drbd_conf *mdev, enum drbd_conns side) 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; } Loading @@ -1663,8 +1681,8 @@ int drbd_worker(struct drbd_thread *thi) 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. Loading @@ -1676,57 +1694,44 @@ int drbd_worker(struct drbd_thread *thi) * * 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, 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; } Loading
drivers/block/drbd/drbd_worker.c +51 −46 Original line number Diff line number Diff line Loading @@ -1624,35 +1624,53 @@ void drbd_start_resync(struct drbd_conf *mdev, enum drbd_conns side) 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; } Loading @@ -1663,8 +1681,8 @@ int drbd_worker(struct drbd_thread *thi) 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. Loading @@ -1676,57 +1694,44 @@ int drbd_worker(struct drbd_thread *thi) * * 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, 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; }