summary refs log tree commit diff
path: root/net/ceph
diff options
context:
space:
mode:
authorIlya Dryomov <idryomov@gmail.com>2020-11-06 17:07:07 +0100
committerIlya Dryomov <idryomov@gmail.com>2020-12-14 23:21:48 +0100
commit3596f4c1241d3c9b6a7cb03b7209c1897c3a5390 (patch)
tree57126074089c8729c05169a68827461b2f6bcd55 /net/ceph
parent90b6561a0525d0888d5d705e343bacaaacd3c021 (diff)
downloadlinux-3596f4c1241d3c9b6a7cb03b7209c1897c3a5390.tar.gz
libceph: split protocol reset bits out of reset_connection()
Move protocol reset bits into ceph_con_reset_protocol(), leaving
just session reset bits.

Note that con->out_skip is now reset on faults.  This fixes a crash
in the case of a stateful session getting a fault while in the middle
of revoking a message.

Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
Diffstat (limited to 'net/ceph')
-rw-r--r--net/ceph/messenger.c50
1 files changed, 24 insertions, 26 deletions
diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c
index a73525de7b70..37166f130d44 100644
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -613,6 +613,25 @@ static int con_close_socket(struct ceph_connection *con)
 	return rc;
 }
 
+static void ceph_con_reset_protocol(struct ceph_connection *con)
+{
+	dout("%s con %p\n", __func__, con);
+
+	con_close_socket(con);
+	if (con->in_msg) {
+		WARN_ON(con->in_msg->con != con);
+		ceph_msg_put(con->in_msg);
+		con->in_msg = NULL;
+	}
+	if (con->out_msg) {
+		WARN_ON(con->out_msg->con != con);
+		ceph_msg_put(con->out_msg);
+		con->out_msg = NULL;
+	}
+
+	con->out_skip = 0;
+}
+
 /*
  * Reset a connection.  Discard all incoming and outgoing messages
  * and clear *_seq state.
@@ -637,26 +656,16 @@ static void reset_connection(struct ceph_connection *con)
 	/* reset connection, out_queue, msg_ and connect_seq */
 	/* discard existing out_queue and msg_seq */
 	dout("reset_connection %p\n", con);
+
+	WARN_ON(con->in_msg);
+	WARN_ON(con->out_msg);
 	ceph_msg_remove_list(&con->out_queue);
 	ceph_msg_remove_list(&con->out_sent);
 
-	if (con->in_msg) {
-		BUG_ON(con->in_msg->con != con);
-		ceph_msg_put(con->in_msg);
-		con->in_msg = NULL;
-	}
-
 	con->connect_seq = 0;
 	con->out_seq = 0;
-	if (con->out_msg) {
-		BUG_ON(con->out_msg->con != con);
-		ceph_msg_put(con->out_msg);
-		con->out_msg = NULL;
-	}
 	con->in_seq = 0;
 	con->in_seq_acked = 0;
-
-	con->out_skip = 0;
 }
 
 /*
@@ -673,10 +682,10 @@ void ceph_con_close(struct ceph_connection *con)
 	con_flag_clear(con, CON_FLAG_WRITE_PENDING);
 	con_flag_clear(con, CON_FLAG_BACKOFF);
 
+	ceph_con_reset_protocol(con);
 	reset_connection(con);
 	con->peer_global_seq = 0;
 	cancel_con(con);
-	con_close_socket(con);
 	mutex_unlock(&con->mutex);
 }
 EXPORT_SYMBOL(ceph_con_close);
@@ -2986,7 +2995,7 @@ static void con_fault(struct ceph_connection *con)
 	       con->state != CON_STATE_NEGOTIATING &&
 	       con->state != CON_STATE_OPEN);
 
-	con_close_socket(con);
+	ceph_con_reset_protocol(con);
 
 	if (con_flag_test(con, CON_FLAG_LOSSYTX)) {
 		dout("fault on LOSSYTX channel, marking CLOSED\n");
@@ -2994,17 +3003,6 @@ static void con_fault(struct ceph_connection *con)
 		return;
 	}
 
-	if (con->in_msg) {
-		BUG_ON(con->in_msg->con != con);
-		ceph_msg_put(con->in_msg);
-		con->in_msg = NULL;
-	}
-	if (con->out_msg) {
-		BUG_ON(con->out_msg->con != con);
-		ceph_msg_put(con->out_msg);
-		con->out_msg = NULL;
-	}
-
 	/* Requeue anything that hasn't been acked */
 	list_splice_init(&con->out_sent, &con->out_queue);