diff options
author | Lars Ellenberg <lars.ellenberg@linbit.com> | 2010-10-14 07:57:07 -0400 |
---|---|---|
committer | Philipp Reisner <philipp.reisner@linbit.com> | 2010-10-14 13:08:32 -0400 |
commit | 9d282875d85ebc2b49362310677fc0dcd91b9db9 (patch) | |
tree | bbbb183462f56b4b065e6dcc5e686587f90ce192 /drivers/block | |
parent | 0f8488e1608b6e30e705460f8110888c645f7f9f (diff) |
drbd: drop wrong debug asserts, fix recently introduced race
commit 2372c38caadeaebc68a5ee190782c2a0df01edc3
drbd: fix for possible deadlock on IO error during resync
introduced a new ASSERT, which turns out to be wrong. Drop it.
Also serialize the state change to D_DISKLESS with the after state
change work of the -> D_FAILED transition, don't open a new race.
Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
Diffstat (limited to 'drivers/block')
-rw-r--r-- | drivers/block/drbd/drbd_main.c | 28 |
1 files changed, 19 insertions, 9 deletions
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index f89b97466d07..342574f6d92e 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c | |||
@@ -1393,17 +1393,22 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os, | |||
1393 | } | 1393 | } |
1394 | 1394 | ||
1395 | if (os.disk > D_DISKLESS && ns.disk == D_DISKLESS) { | 1395 | if (os.disk > D_DISKLESS && ns.disk == D_DISKLESS) { |
1396 | int c = atomic_read(&mdev->local_cnt); | 1396 | /* We must still be diskless, |
1397 | 1397 | * re-attach has to be serialized with this! */ | |
1398 | if (mdev->state.disk != D_DISKLESS) | ||
1399 | dev_err(DEV, | ||
1400 | "ASSERT FAILED: disk is %s while going diskless\n", | ||
1401 | drbd_disk_str(mdev->state.disk)); | ||
1402 | |||
1403 | /* we cannot assert local_cnt == 0 here, as get_ldev_if_state | ||
1404 | * will inc/dec it frequently. Since we became D_DISKLESS, no | ||
1405 | * one has touched the protected members anymore, though, so we | ||
1406 | * are safe to free them here. */ | ||
1398 | if (drbd_send_state(mdev)) | 1407 | if (drbd_send_state(mdev)) |
1399 | dev_warn(DEV, "Notified peer that I detached my disk.\n"); | 1408 | dev_warn(DEV, "Notified peer that I detached my disk.\n"); |
1400 | else | 1409 | else |
1401 | dev_err(DEV, "Sending state for detach failed\n"); | 1410 | dev_err(DEV, "Sending state for detach failed\n"); |
1402 | 1411 | ||
1403 | if (c != 0) { | ||
1404 | dev_err(DEV, "Logic bug, local_cnt=%d, but should be 0\n", c); | ||
1405 | wait_event(mdev->misc_wait, !atomic_read(&mdev->local_cnt)); | ||
1406 | } | ||
1407 | lc_destroy(mdev->resync); | 1412 | lc_destroy(mdev->resync); |
1408 | mdev->resync = NULL; | 1413 | mdev->resync = NULL; |
1409 | lc_destroy(mdev->act_log); | 1414 | lc_destroy(mdev->act_log); |
@@ -3723,8 +3728,10 @@ static int w_bitmap_io(struct drbd_conf *mdev, struct drbd_work *w, int unused) | |||
3723 | static int w_go_diskless(struct drbd_conf *mdev, struct drbd_work *w, int unused) | 3728 | static int w_go_diskless(struct drbd_conf *mdev, struct drbd_work *w, int unused) |
3724 | { | 3729 | { |
3725 | D_ASSERT(mdev->state.disk == D_FAILED); | 3730 | D_ASSERT(mdev->state.disk == D_FAILED); |
3726 | D_ASSERT(atomic_read(&mdev->local_cnt) == 0); | 3731 | /* we cannot assert local_cnt == 0 here, as get_ldev_if_state will |
3727 | 3732 | * inc/dec it frequently. Once we are D_DISKLESS, no one will touch | |
3733 | * the protected members anymore, though, so in the after_state_ch work | ||
3734 | * it will be safe to free them. */ | ||
3728 | drbd_force_state(mdev, NS(disk, D_DISKLESS)); | 3735 | drbd_force_state(mdev, NS(disk, D_DISKLESS)); |
3729 | 3736 | ||
3730 | clear_bit(GO_DISKLESS, &mdev->flags); | 3737 | clear_bit(GO_DISKLESS, &mdev->flags); |
@@ -3735,7 +3742,10 @@ void drbd_go_diskless(struct drbd_conf *mdev) | |||
3735 | { | 3742 | { |
3736 | D_ASSERT(mdev->state.disk == D_FAILED); | 3743 | D_ASSERT(mdev->state.disk == D_FAILED); |
3737 | if (!test_and_set_bit(GO_DISKLESS, &mdev->flags)) | 3744 | if (!test_and_set_bit(GO_DISKLESS, &mdev->flags)) |
3738 | drbd_queue_work_front(&mdev->data.work, &mdev->go_diskless); | 3745 | drbd_queue_work(&mdev->data.work, &mdev->go_diskless); |
3746 | /* don't drbd_queue_work_front, | ||
3747 | * we need to serialize with the after_state_ch work | ||
3748 | * of the -> D_FAILED transition. */ | ||
3739 | } | 3749 | } |
3740 | 3750 | ||
3741 | /** | 3751 | /** |