aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/drbd/drbd_nl.c
diff options
context:
space:
mode:
authorLars Ellenberg <lars.ellenberg@linbit.com>2010-09-01 03:50:23 -0400
committerPhilipp Reisner <philipp.reisner@linbit.com>2010-10-14 12:38:27 -0400
commitc518d04fdec3d8b9d6f8b2228040934de9ee6708 (patch)
tree8d749aa26634287fe59fba8fe181b0f43f36af1a /drivers/block/drbd/drbd_nl.c
parent0778286a133d2d3f81861a4e5db308e359583006 (diff)
drbd: fix race between deconfiguring and reconfiguring network
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>
Diffstat (limited to 'drivers/block/drbd/drbd_nl.c')
-rw-r--r--drivers/block/drbd/drbd_nl.c6
1 files changed, 4 insertions, 2 deletions
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c
index 6742652c8abc..d066190f997a 100644
--- a/drivers/block/drbd/drbd_nl.c
+++ b/drivers/block/drbd/drbd_nl.c
@@ -750,14 +750,16 @@ void drbd_setup_queue_param(struct drbd_conf *mdev, unsigned int max_seg_s) __mu
750/* serialize deconfig (worker exiting, doing cleanup) 750/* serialize deconfig (worker exiting, doing cleanup)
751 * and reconfig (drbdsetup disk, drbdsetup net) 751 * and reconfig (drbdsetup disk, drbdsetup net)
752 * 752 *
753 * wait for a potentially exiting worker, then restart it, 753 * Wait for a potentially exiting worker, then restart it,
754 * or start a new one. 754 * or start a new one. Flush any pending work, there may still be an
755 * after_state_change queued.
755 */ 756 */
756static void drbd_reconfig_start(struct drbd_conf *mdev) 757static void drbd_reconfig_start(struct drbd_conf *mdev)
757{ 758{
758 wait_event(mdev->state_wait, !test_and_set_bit(CONFIG_PENDING, &mdev->flags)); 759 wait_event(mdev->state_wait, !test_and_set_bit(CONFIG_PENDING, &mdev->flags));
759 wait_event(mdev->state_wait, !test_bit(DEVICE_DYING, &mdev->flags)); 760 wait_event(mdev->state_wait, !test_bit(DEVICE_DYING, &mdev->flags));
760 drbd_thread_start(&mdev->worker); 761 drbd_thread_start(&mdev->worker);
762 drbd_flush_workqueue(mdev);
761} 763}
762 764
763/* if still unconfigured, stops worker again. 765/* if still unconfigured, stops worker again.