diff options
author | Philipp Reisner <philipp.reisner@linbit.com> | 2012-03-26 10:47:11 -0400 |
---|---|---|
committer | Philipp Reisner <philipp.reisner@linbit.com> | 2012-05-09 09:16:55 -0400 |
commit | 197296ffed71b7d5056d8618a07fec145b040303 (patch) | |
tree | 7ee407b7f0536fb2cf7911ab0d7e48acce81cd4e /drivers/block/drbd/drbd_main.c | |
parent | 46385c84acd6654d3a38c9c7af1921dbded74aa2 (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.c | 13 |
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. |