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>
diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c
index 9c8bcce..956cdda 100644
--- a/drivers/block/drbd/drbd_receiver.c
+++ b/drivers/block/drbd/drbd_receiver.c
@@ -4213,20 +4213,8 @@
 
 	spin_unlock_irq(&tconn->req_lock);
 
-	if (oc == C_DISCONNECTING) {
-		struct net_conf *old_conf;
-
-		mutex_lock(&tconn->net_conf_update);
-		old_conf = tconn->net_conf;
-		rcu_assign_pointer(tconn->net_conf, NULL);
-		conn_free_crypto(tconn);
-		mutex_unlock(&tconn->net_conf_update);
-
-		synchronize_rcu();
-		kfree(old_conf);
-
+	if (oc == C_DISCONNECTING)
 		conn_request_state(tconn, NS(conn, C_STANDALONE), CS_VERBOSE | CS_HARD);
-	}
 }
 
 static int drbd_disconnected(int vnr, void *p, void *data)