diff options
author | Lars Ellenberg <lars.ellenberg@linbit.com> | 2010-09-01 03:50:23 -0400 |
---|---|---|
committer | Philipp Reisner <philipp.reisner@linbit.com> | 2010-10-14 12:38:27 -0400 |
commit | c518d04fdec3d8b9d6f8b2228040934de9ee6708 (patch) | |
tree | 8d749aa26634287fe59fba8fe181b0f43f36af1a /drivers/block/drbd/drbd_nl.c | |
parent | 0778286a133d2d3f81861a4e5db308e359583006 (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.c | 6 |
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 | */ |
756 | static void drbd_reconfig_start(struct drbd_conf *mdev) | 757 | static 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. |