diff options
author | Philipp Reisner | 2012-03-26 16:47:11 +0200 |
---|---|---|
committer | Philipp Reisner | 2012-05-09 15:16:55 +0200 |
commit | 197296ffed71b7d5056d8618a07fec145b040303 (patch) | |
tree | 7ee407b7f0536fb2cf7911ab0d7e48acce81cd4e /drivers/block/drbd/drbd_receiver.c | |
parent | drbd: move put_ldev from __req_mod() to the endio callback (diff) | |
download | kernel-qcow2-linux-197296ffed71b7d5056d8618a07fec145b040303.tar.gz kernel-qcow2-linux-197296ffed71b7d5056d8618a07fec145b040303.tar.xz kernel-qcow2-linux-197296ffed71b7d5056d8618a07fec145b040303.zip |
drbd: Delay/reject other state changes while establishing a connection
Changes to the role and disk state should be delayed or rejected
while we establish a connection.
This is necessary, since the peer will base its resync decision
on the UUIDs and the state we sent in the drbd_connect() function.
The most prominent example for this race is becoming primary after
sending state and UUIDs and before the state changes to C_WF_CONNECTION.
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_receiver.c')
-rw-r--r-- | drivers/block/drbd/drbd_receiver.c | 10 |
1 files changed, 9 insertions, 1 deletions
diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index d601501c336a..9db93ff11c02 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -751,6 +751,7 @@ static int drbd_connect(struct drbd_conf *mdev) { struct socket *s, *sock, *msock; int try, h, ok; + enum drbd_state_rv rv; D_ASSERT(!mdev->data.socket); @@ -897,6 +898,7 @@ retry: if (drbd_send_protocol(mdev) == -1) return -1; + set_bit(STATE_SENT, &mdev->flags); drbd_send_sync_param(mdev, &mdev->sync_conf); drbd_send_sizes(mdev, 0, 0); drbd_send_uuids(mdev); @@ -904,7 +906,13 @@ retry: clear_bit(USE_DEGR_WFC_T, &mdev->flags); clear_bit(RESIZE_PENDING, &mdev->flags); - if (drbd_request_state(mdev, NS(conn, C_WF_REPORT_PARAMS)) < SS_SUCCESS) + spin_lock_irq(&mdev->req_lock); + rv = _drbd_set_state(_NS(mdev, conn, C_WF_REPORT_PARAMS), CS_VERBOSE, NULL); + if (mdev->state.conn != C_WF_REPORT_PARAMS) + clear_bit(STATE_SENT, &mdev->flags); + spin_unlock_irq(&mdev->req_lock); + + if (rv < SS_SUCCESS) return 0; drbd_thread_start(&mdev->asender); |