aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/drbd/drbd_receiver.c
diff options
context:
space:
mode:
authorLars Ellenberg <lars.ellenberg@linbit.com>2011-05-02 04:45:05 -0400
committerPhilipp Reisner <philipp.reisner@linbit.com>2012-11-08 10:53:00 -0500
commitf3dfa40a67c354a5886c5ae53a9c5d3a2c6fd06e (patch)
treee85ab6fe143681814b395ed5ece180df8d090201 /drivers/block/drbd/drbd_receiver.c
parent88104ca458dff8ed7db935936b91b9af4422c9cd (diff)
drbd: fix race when forcefully disconnecting
If a forced disconnect hits a restarting receiver right after it passed its final "if (C_DISCONNECTING)" test in drbdd_init(), but before it was actually restarted by drbd_thread_setup, we could be left with a connection stuck in C_DISCONNECTING, never reaching C_STANDALONE, which would be necessary to take it down or reconfigure it. Move the last cleanup into w_after_conn_state_ch(), and do an additional state change request in conn_try_disconnect(), just in case. 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.c14
1 files changed, 1 insertions, 13 deletions
diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c
index 9c8bcce0e684..956cdda93430 100644
--- a/drivers/block/drbd/drbd_receiver.c
+++ b/drivers/block/drbd/drbd_receiver.c
@@ -4213,20 +4213,8 @@ static void drbd_disconnect(struct drbd_tconn *tconn)
4213 4213
4214 spin_unlock_irq(&tconn->req_lock); 4214 spin_unlock_irq(&tconn->req_lock);
4215 4215
4216 if (oc == C_DISCONNECTING) { 4216 if (oc == C_DISCONNECTING)
4217 struct net_conf *old_conf;
4218
4219 mutex_lock(&tconn->net_conf_update);
4220 old_conf = tconn->net_conf;
4221 rcu_assign_pointer(tconn->net_conf, NULL);
4222 conn_free_crypto(tconn);
4223 mutex_unlock(&tconn->net_conf_update);
4224
4225 synchronize_rcu();
4226 kfree(old_conf);
4227
4228 conn_request_state(tconn, NS(conn, C_STANDALONE), CS_VERBOSE | CS_HARD); 4217 conn_request_state(tconn, NS(conn, C_STANDALONE), CS_VERBOSE | CS_HARD);
4229 }
4230} 4218}
4231 4219
4232static int drbd_disconnected(int vnr, void *p, void *data) 4220static int drbd_disconnected(int vnr, void *p, void *data)