drbd: fix race between deconfiguring and reconfiguring network
authorLars Ellenberg <lars.ellenberg@linbit.com>
Wed, 1 Sep 2010 07:50:23 +0000 (09:50 +0200)
committerPhilipp Reisner <philipp.reisner@linbit.com>
Thu, 14 Oct 2010 16:38:27 +0000 (18:38 +0200)
If a drbd_nl_net_conf hits the small window between the state change
to C_STANDALONE and the corresponding cleanup in after_state_ch,
that cleanup would throw away stuff we now need again,
and later trigger BUG_ON()s.

Fixed by properly serializing the new config request with
any pending cleanup.

Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
drivers/block/drbd/drbd_nl.c

index 6742652c8abc7f8b65fe0b211cd4d11bc62961e9..d066190f997a9bdf254a2b6f1488ce158dab9d22 100644 (file)
@@ -750,14 +750,16 @@ void drbd_setup_queue_param(struct drbd_conf *mdev, unsigned int max_seg_s) __mu
 /* serialize deconfig (worker exiting, doing cleanup)
  * and reconfig (drbdsetup disk, drbdsetup net)
  *
- * wait for a potentially exiting worker, then restart it,
- * or start a new one.
+ * Wait for a potentially exiting worker, then restart it,
+ * or start a new one.  Flush any pending work, there may still be an
+ * after_state_change queued.
  */
 static void drbd_reconfig_start(struct drbd_conf *mdev)
 {
        wait_event(mdev->state_wait, !test_and_set_bit(CONFIG_PENDING, &mdev->flags));
        wait_event(mdev->state_wait, !test_bit(DEVICE_DYING, &mdev->flags));
        drbd_thread_start(&mdev->worker);
+       drbd_flush_workqueue(mdev);
 }
 
 /* if still unconfigured, stops worker again.