diff options
author | Philipp Reisner <philipp.reisner@linbit.com> | 2013-03-27 09:08:35 -0400 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2013-03-28 12:10:24 -0400 |
commit | a700471bf335965e7603273fd51034415553246a (patch) | |
tree | 2993750346f31eda81e1b0d531469087ace71206 /drivers | |
parent | 2d56a974f36ffd1d00aa897bd55e28079aa9e5b7 (diff) |
drbd: abort start of resync early, if it raced with connection breakage
We've seen a spurious full resync, because a connection breakage
raced with drbd_start_resync(, C_SYNC_TARGET),
and the resulting state change request intended to start the resync
ended up looking like a local invalidate.
Fix:
Double check the state inside the lock,
and don't even request that state change,
if we had connection or IO problems.
Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/block/drbd/drbd_worker.c | 4 |
1 files changed, 3 insertions, 1 deletions
diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c index f41e224caa7c..7f51f88b0a80 100644 --- a/drivers/block/drbd/drbd_worker.c +++ b/drivers/block/drbd/drbd_worker.c | |||
@@ -1653,7 +1653,9 @@ void drbd_start_resync(struct drbd_conf *mdev, enum drbd_conns side) | |||
1653 | clear_bit(B_RS_H_DONE, &mdev->flags); | 1653 | clear_bit(B_RS_H_DONE, &mdev->flags); |
1654 | 1654 | ||
1655 | write_lock_irq(&global_state_lock); | 1655 | write_lock_irq(&global_state_lock); |
1656 | if (!get_ldev_if_state(mdev, D_NEGOTIATING)) { | 1656 | /* Did some connection breakage or IO error race with us? */ |
1657 | if (mdev->state.conn < C_CONNECTED | ||
1658 | || !get_ldev_if_state(mdev, D_NEGOTIATING)) { | ||
1657 | write_unlock_irq(&global_state_lock); | 1659 | write_unlock_irq(&global_state_lock); |
1658 | mutex_unlock(mdev->state_mutex); | 1660 | mutex_unlock(mdev->state_mutex); |
1659 | return; | 1661 | return; |