aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/drbd/drbd_main.c
diff options
context:
space:
mode:
authorPhilipp Reisner <philipp.reisner@linbit.com>2012-03-26 10:47:11 -0400
committerPhilipp Reisner <philipp.reisner@linbit.com>2012-05-09 09:16:55 -0400
commit197296ffed71b7d5056d8618a07fec145b040303 (patch)
tree7ee407b7f0536fb2cf7911ab0d7e48acce81cd4e /drivers/block/drbd/drbd_main.c
parent46385c84acd6654d3a38c9c7af1921dbded74aa2 (diff)
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_main.c')
-rw-r--r--drivers/block/drbd/drbd_main.c13
1 files changed, 13 insertions, 0 deletions
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c
index 519f286a4299..deccff3af774 100644
--- a/drivers/block/drbd/drbd_main.c
+++ b/drivers/block/drbd/drbd_main.c
@@ -841,6 +841,13 @@ is_valid_state_transition(struct drbd_conf *mdev, union drbd_state ns,
841 if (ns.conn == os.conn && ns.conn == C_WF_REPORT_PARAMS) 841 if (ns.conn == os.conn && ns.conn == C_WF_REPORT_PARAMS)
842 rv = SS_IN_TRANSIENT_STATE; 842 rv = SS_IN_TRANSIENT_STATE;
843 843
844 /* While establishing a connection only allow cstate to change.
845 Delay/refuse role changes, detach attach etc... */
846 if (test_bit(STATE_SENT, &mdev->flags) &&
847 !(os.conn == C_WF_REPORT_PARAMS ||
848 (ns.conn == C_WF_REPORT_PARAMS && os.conn == C_WF_CONNECTION)))
849 rv = SS_IN_TRANSIENT_STATE;
850
844 if ((ns.conn == C_VERIFY_S || ns.conn == C_VERIFY_T) && os.conn < C_CONNECTED) 851 if ((ns.conn == C_VERIFY_S || ns.conn == C_VERIFY_T) && os.conn < C_CONNECTED)
845 rv = SS_NEED_CONNECTION; 852 rv = SS_NEED_CONNECTION;
846 853
@@ -1668,6 +1675,12 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os,
1668 if (os.disk < D_UP_TO_DATE && os.conn >= C_SYNC_SOURCE && ns.conn == C_CONNECTED) 1675 if (os.disk < D_UP_TO_DATE && os.conn >= C_SYNC_SOURCE && ns.conn == C_CONNECTED)
1669 drbd_send_state(mdev, ns); 1676 drbd_send_state(mdev, ns);
1670 1677
1678 /* Wake up role changes, that were delayed because of connection establishing */
1679 if (os.conn == C_WF_REPORT_PARAMS && ns.conn != C_WF_REPORT_PARAMS) {
1680 clear_bit(STATE_SENT, &mdev->flags);
1681 wake_up(&mdev->state_wait);
1682 }
1683
1671 /* This triggers bitmap writeout of potentially still unwritten pages 1684 /* This triggers bitmap writeout of potentially still unwritten pages
1672 * if the resync finished cleanly, or aborted because of peer disk 1685 * if the resync finished cleanly, or aborted because of peer disk
1673 * failure, or because of connection loss. 1686 * failure, or because of connection loss.