aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/drbd
diff options
context:
space:
mode:
authorPhilipp Reisner <philipp.reisner@linbit.com>2013-03-27 09:08:35 -0400
committerJens Axboe <axboe@kernel.dk>2013-03-28 12:10:24 -0400
commita700471bf335965e7603273fd51034415553246a (patch)
tree2993750346f31eda81e1b0d531469087ace71206 /drivers/block/drbd
parent2d56a974f36ffd1d00aa897bd55e28079aa9e5b7 (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/block/drbd')
-rw-r--r--drivers/block/drbd/drbd_worker.c4
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;