libceph: split protocol reset bits out of reset_connection()
authorIlya Dryomov <idryomov@gmail.com>
Fri, 6 Nov 2020 16:07:07 +0000 (17:07 +0100)
committerIlya Dryomov <idryomov@gmail.com>
Mon, 14 Dec 2020 22:21:48 +0000 (23:21 +0100)
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>
net/ceph/messenger.c

index a73525d..37166f1 100644 (file)
@@ -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);