|
| 1 | +rxrpc: Make the local endpoint hold a ref on a connected call |
| 2 | + |
| 3 | +jira LE-1907 |
| 4 | +Rebuild_History Non-Buildable kernel-rt-5.14.0-284.30.1.rt14.315.el9_2 |
| 5 | +commit-author David Howells <dhowells@redhat.com> |
| 6 | +commit 5040011d073d3acdeb58af2b64f84e33bb03abd2 |
| 7 | +Empty-Commit: Cherry-Pick Conflicts during history rebuild. |
| 8 | +Will be included in final tarball splat. Ref for failed cherry-pick at: |
| 9 | +ciq/ciq_backports/kernel-rt-5.14.0-284.30.1.rt14.315.el9_2/5040011d.failed |
| 10 | + |
| 11 | +Make the local endpoint and it's I/O thread hold a reference on a connected |
| 12 | +call until that call is disconnected. Without this, we're reliant on |
| 13 | +either the AF_RXRPC socket to hold a ref (which is dropped when the call is |
| 14 | +released) or a queued work item to hold a ref (the work item is being |
| 15 | +replaced with the I/O thread). |
| 16 | + |
| 17 | + Signed-off-by: David Howells <dhowells@redhat.com> |
| 18 | +cc: Marc Dionne <marc.dionne@auristor.com> |
| 19 | +cc: linux-afs@lists.infradead.org |
| 20 | +(cherry picked from commit 5040011d073d3acdeb58af2b64f84e33bb03abd2) |
| 21 | + Signed-off-by: Jonathan Maple <jmaple@ciq.com> |
| 22 | + |
| 23 | +# Conflicts: |
| 24 | +# include/trace/events/rxrpc.h |
| 25 | +# net/rxrpc/call_object.c |
| 26 | +# net/rxrpc/conn_object.c |
| 27 | +diff --cc include/trace/events/rxrpc.h |
| 28 | +index 2a52121d73a0,b526d982da7e..000000000000 |
| 29 | +--- a/include/trace/events/rxrpc.h |
| 30 | ++++ b/include/trace/events/rxrpc.h |
| 31 | +@@@ -82,10 -159,12 +83,15 @@@ |
| 32 | + EM(rxrpc_call_get_userid, "GET user-id ") \ |
| 33 | + EM(rxrpc_call_new_client, "NEW client ") \ |
| 34 | + EM(rxrpc_call_new_prealloc_service, "NEW prealloc") \ |
| 35 | + + EM(rxrpc_call_put_already_queued, "PUT alreadyq") \ |
| 36 | + EM(rxrpc_call_put_discard_prealloc, "PUT disc-pre") \ |
| 37 | +++<<<<<<< HEAD |
| 38 | +++======= |
| 39 | ++ EM(rxrpc_call_put_discard_error, "PUT disc-err") \ |
| 40 | ++ EM(rxrpc_call_put_io_thread, "PUT iothread") \ |
| 41 | +++>>>>>>> 5040011d073d (rxrpc: Make the local endpoint hold a ref on a connected call) |
| 42 | + EM(rxrpc_call_put_input, "PUT input ") \ |
| 43 | + EM(rxrpc_call_put_kernel, "PUT kernel ") \ |
| 44 | + - EM(rxrpc_call_put_poke, "PUT poke ") \ |
| 45 | + EM(rxrpc_call_put_recvmsg, "PUT recvmsg ") \ |
| 46 | + EM(rxrpc_call_put_release_sock, "PUT rls-sock") \ |
| 47 | + EM(rxrpc_call_put_release_sock_tba, "PUT rls-sk-a") \ |
| 48 | +diff --cc net/rxrpc/call_object.c |
| 49 | +index ad495d0d21a8,239fc3c75079..000000000000 |
| 50 | +--- a/net/rxrpc/call_object.c |
| 51 | ++++ b/net/rxrpc/call_object.c |
| 52 | +@@@ -405,6 -430,31 +405,34 @@@ void rxrpc_incoming_call(struct rxrpc_s |
| 53 | + call->state = RXRPC_CALL_SERVER_SECURING; |
| 54 | + call->cong_tstamp = skb->tstamp; |
| 55 | + |
| 56 | +++<<<<<<< HEAD |
| 57 | +++======= |
| 58 | ++ spin_lock(&conn->state_lock); |
| 59 | ++ |
| 60 | ++ switch (conn->state) { |
| 61 | ++ case RXRPC_CONN_SERVICE_UNSECURED: |
| 62 | ++ case RXRPC_CONN_SERVICE_CHALLENGING: |
| 63 | ++ call->state = RXRPC_CALL_SERVER_SECURING; |
| 64 | ++ break; |
| 65 | ++ case RXRPC_CONN_SERVICE: |
| 66 | ++ call->state = RXRPC_CALL_SERVER_RECV_REQUEST; |
| 67 | ++ break; |
| 68 | ++ |
| 69 | ++ case RXRPC_CONN_REMOTELY_ABORTED: |
| 70 | ++ __rxrpc_set_call_completion(call, RXRPC_CALL_REMOTELY_ABORTED, |
| 71 | ++ conn->abort_code, conn->error); |
| 72 | ++ break; |
| 73 | ++ case RXRPC_CONN_LOCALLY_ABORTED: |
| 74 | ++ __rxrpc_abort_call("CON", call, 1, |
| 75 | ++ conn->abort_code, conn->error); |
| 76 | ++ break; |
| 77 | ++ default: |
| 78 | ++ BUG(); |
| 79 | ++ } |
| 80 | ++ |
| 81 | ++ rxrpc_get_call(call, rxrpc_call_get_io_thread); |
| 82 | ++ |
| 83 | +++>>>>>>> 5040011d073d (rxrpc: Make the local endpoint hold a ref on a connected call) |
| 84 | + /* Set the channel for this call. We don't get channel_lock as we're |
| 85 | + * only defending against the data_ready handler (which we're called |
| 86 | + * from) and the RESPONSE packet parser (which is only really |
| 87 | +diff --cc net/rxrpc/conn_object.c |
| 88 | +index 156bd26daf74,2bd3f6288895..000000000000 |
| 89 | +--- a/net/rxrpc/conn_object.c |
| 90 | ++++ b/net/rxrpc/conn_object.c |
| 91 | +@@@ -210,50 -184,25 +213,60 @@@ void rxrpc_disconnect_call(struct rxrpc |
| 92 | + call->peer->cong_ssthresh = call->cong_ssthresh; |
| 93 | + |
| 94 | + if (!hlist_unhashed(&call->error_link)) { |
| 95 | + - spin_lock(&call->peer->lock); |
| 96 | + - hlist_del_init(&call->error_link); |
| 97 | + - spin_unlock(&call->peer->lock); |
| 98 | + + spin_lock_bh(&call->peer->lock); |
| 99 | + + hlist_del_rcu(&call->error_link); |
| 100 | + + spin_unlock_bh(&call->peer->lock); |
| 101 | + } |
| 102 | + |
| 103 | +- if (rxrpc_is_client_call(call)) |
| 104 | +- return rxrpc_disconnect_client_call(conn->bundle, call); |
| 105 | ++ if (rxrpc_is_client_call(call)) { |
| 106 | ++ rxrpc_disconnect_client_call(conn->bundle, call); |
| 107 | ++ } else { |
| 108 | ++ spin_lock(&conn->bundle->channel_lock); |
| 109 | ++ __rxrpc_disconnect_call(conn, call); |
| 110 | ++ spin_unlock(&conn->bundle->channel_lock); |
| 111 | + |
| 112 | +- spin_lock(&conn->bundle->channel_lock); |
| 113 | +- __rxrpc_disconnect_call(conn, call); |
| 114 | +- spin_unlock(&conn->bundle->channel_lock); |
| 115 | ++ conn->idle_timestamp = jiffies; |
| 116 | ++ if (atomic_dec_and_test(&conn->active)) |
| 117 | ++ rxrpc_set_service_reap_timer(conn->rxnet, |
| 118 | ++ jiffies + rxrpc_connection_expiry); |
| 119 | ++ } |
| 120 | + |
| 121 | +++<<<<<<< HEAD |
| 122 | + + set_bit(RXRPC_CALL_DISCONNECTED, &call->flags); |
| 123 | + + conn->idle_timestamp = jiffies; |
| 124 | + +} |
| 125 | + + |
| 126 | + +/* |
| 127 | + + * Kill off a connection. |
| 128 | + + */ |
| 129 | + +void rxrpc_kill_connection(struct rxrpc_connection *conn) |
| 130 | + +{ |
| 131 | + + struct rxrpc_net *rxnet = conn->params.local->rxnet; |
| 132 | + + |
| 133 | + + ASSERT(!rcu_access_pointer(conn->channels[0].call) && |
| 134 | + + !rcu_access_pointer(conn->channels[1].call) && |
| 135 | + + !rcu_access_pointer(conn->channels[2].call) && |
| 136 | + + !rcu_access_pointer(conn->channels[3].call)); |
| 137 | + + ASSERT(list_empty(&conn->cache_link)); |
| 138 | + + |
| 139 | + + write_lock(&rxnet->conn_lock); |
| 140 | + + list_del_init(&conn->proc_link); |
| 141 | + + write_unlock(&rxnet->conn_lock); |
| 142 | + + |
| 143 | + + /* Drain the Rx queue. Note that even though we've unpublished, an |
| 144 | + + * incoming packet could still be being added to our Rx queue, so we |
| 145 | + + * will need to drain it again in the RCU cleanup handler. |
| 146 | + + */ |
| 147 | + + rxrpc_purge_queue(&conn->rx_queue); |
| 148 | + + |
| 149 | + + /* Leave final destruction to RCU. The connection processor work item |
| 150 | + + * must carry a ref on the connection to prevent us getting here whilst |
| 151 | + + * it is queued or running. |
| 152 | + + */ |
| 153 | + + call_rcu(&conn->rcu, rxrpc_destroy_connection); |
| 154 | +++======= |
| 155 | ++ rxrpc_put_call(call, rxrpc_call_put_io_thread); |
| 156 | +++>>>>>>> 5040011d073d (rxrpc: Make the local endpoint hold a ref on a connected call) |
| 157 | + } |
| 158 | + |
| 159 | + /* |
| 160 | +* Unmerged path include/trace/events/rxrpc.h |
| 161 | +* Unmerged path net/rxrpc/call_object.c |
| 162 | +diff --git a/net/rxrpc/conn_client.c b/net/rxrpc/conn_client.c |
| 163 | +index 827c1308297c..0576723401c8 100644 |
| 164 | +--- a/net/rxrpc/conn_client.c |
| 165 | ++++ b/net/rxrpc/conn_client.c |
| 166 | +@@ -714,8 +714,11 @@ int rxrpc_connect_call(struct rxrpc_sock *rx, |
| 167 | + |
| 168 | + rxrpc_discard_expired_client_conns(&rxnet->client_conn_reaper); |
| 169 | + |
| 170 | ++ rxrpc_get_call(call, rxrpc_call_get_io_thread); |
| 171 | ++ |
| 172 | + bundle = rxrpc_prep_call(rx, call, cp, srx, gfp); |
| 173 | + if (IS_ERR(bundle)) { |
| 174 | ++ rxrpc_put_call(call, rxrpc_call_get_io_thread); |
| 175 | + ret = PTR_ERR(bundle); |
| 176 | + goto out; |
| 177 | + } |
| 178 | +@@ -805,7 +808,6 @@ void rxrpc_disconnect_client_call(struct rxrpc_bundle *bundle, struct rxrpc_call |
| 179 | + _enter("c=%x", call->debug_id); |
| 180 | + |
| 181 | + spin_lock(&bundle->channel_lock); |
| 182 | +- set_bit(RXRPC_CALL_DISCONNECTED, &call->flags); |
| 183 | + |
| 184 | + /* Calls that have never actually been assigned a channel can simply be |
| 185 | + * discarded. |
| 186 | +@@ -897,8 +899,6 @@ void rxrpc_disconnect_client_call(struct rxrpc_bundle *bundle, struct rxrpc_call |
| 187 | + |
| 188 | + out: |
| 189 | + spin_unlock(&bundle->channel_lock); |
| 190 | +- _leave(""); |
| 191 | +- return; |
| 192 | + } |
| 193 | + |
| 194 | + /* |
| 195 | +* Unmerged path net/rxrpc/conn_object.c |
0 commit comments