aboutsummaryrefslogtreecommitdiff
path: root/drivers/block/drbd/drbd_receiver.c
diff options
context:
space:
mode:
authorPhilipp Reisner <philipp.reisner@linbit.com>2012-04-06 12:07:34 +0200
committerPhilipp Reisner <philipp.reisner@linbit.com>2012-11-08 16:58:26 +0100
commita1096a6e9da7885ec9e11d93aa459685a33fa4d9 (patch)
tree36ee9aba8823ed51b0c71176df5f2b891ba0c06a /drivers/block/drbd/drbd_receiver.c
parent27eb13e99b515c52ba5a151a1acce6afb8a9b2b6 (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.c8
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);