diff options
author | Philipp Reisner <philipp.reisner@linbit.com> | 2012-04-06 12:07:34 +0200 |
---|---|---|
committer | Philipp Reisner <philipp.reisner@linbit.com> | 2012-11-08 16:58:26 +0100 |
commit | a1096a6e9da7885ec9e11d93aa459685a33fa4d9 (patch) | |
tree | 36ee9aba8823ed51b0c71176df5f2b891ba0c06a /drivers/block/drbd/drbd_receiver.c | |
parent | 27eb13e99b515c52ba5a151a1acce6afb8a9b2b6 (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_receiver.c')
-rw-r--r-- | drivers/block/drbd/drbd_receiver.c | 8 |
1 files changed, 7 insertions, 1 deletions
diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index e8cd4c4acc6..7b690342efa 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -848,6 +848,7 @@ static int conn_connect(struct drbd_tconn *tconn) struct net_conf *nc; int vnr, timeout, try, h, ok; bool discard_my_data; + enum drbd_state_rv rv; if (conn_request_state(tconn, NS(conn, C_WF_CONNECTION), CS_VERBOSE) < SS_SUCCESS) return -2; @@ -1008,6 +1009,8 @@ retry: if (drbd_send_protocol(tconn) == -EOPNOTSUPP) return -1; + set_bit(STATE_SENT, &tconn->flags); + rcu_read_lock(); idr_for_each_entry(&tconn->volumes, mdev, vnr) { kref_get(&mdev->kref); @@ -1024,8 +1027,11 @@ retry: } rcu_read_unlock(); - if (conn_request_state(tconn, NS(conn, C_WF_REPORT_PARAMS), CS_VERBOSE) < SS_SUCCESS) + rv = conn_request_state(tconn, NS(conn, C_WF_REPORT_PARAMS), CS_VERBOSE); + if (rv < SS_SUCCESS) { + clear_bit(STATE_SENT, &tconn->flags); return 0; + } drbd_thread_start(&tconn->asender); |