Skip to content

Commit 03fc55a

Browse files
committed
rxrpc: Only disconnect calls in the I/O thread
Only perform call disconnection in the I/O thread to reduce the locking requirement. This is the first part of a fix for a race that exists between call connection and call disconnection whereby the data transmission code adds the call to the peer error distribution list after the call has been disconnected (say by the rxrpc socket getting closed). The fix is to complete the process of moving call connection, data transmission and call disconnection into the I/O thread and thus forcibly serialising them. Note that the issue may predate the overhaul to an I/O thread model that were included in the merge window for v6.2, but the timing is very much changed by the change given below. Fixes: cf37b59 ("rxrpc: Move DATA transmission into call processor work item") Reported-by: [email protected] Signed-off-by: David Howells <[email protected]> cc: Marc Dionne <[email protected]> cc: [email protected]
1 parent a343b17 commit 03fc55a

File tree

5 files changed

+9
-15
lines changed

5 files changed

+9
-15
lines changed

include/trace/events/rxrpc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
*/
1919
#define rxrpc_call_poke_traces \
2020
EM(rxrpc_call_poke_abort, "Abort") \
21+
EM(rxrpc_call_poke_complete, "Compl") \
2122
EM(rxrpc_call_poke_error, "Error") \
2223
EM(rxrpc_call_poke_idle, "Idle") \
2324
EM(rxrpc_call_poke_start, "Start") \

net/rxrpc/call_event.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -484,8 +484,13 @@ void rxrpc_input_call_event(struct rxrpc_call *call, struct sk_buff *skb)
484484
}
485485

486486
out:
487-
if (call->state == RXRPC_CALL_COMPLETE)
487+
if (call->state == RXRPC_CALL_COMPLETE) {
488488
del_timer_sync(&call->timer);
489+
if (!test_bit(RXRPC_CALL_DISCONNECTED, &call->flags))
490+
rxrpc_disconnect_call(call);
491+
if (call->security)
492+
call->security->free_call_crypto(call);
493+
}
489494
if (call->acks_hard_ack != call->tx_bottom)
490495
rxrpc_shrink_call_tx_buffer(call);
491496
_leave("");

net/rxrpc/call_object.c

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ void rxrpc_poke_call(struct rxrpc_call *call, enum rxrpc_call_poke_trace what)
5050
struct rxrpc_local *local = call->local;
5151
bool busy;
5252

53-
if (call->state < RXRPC_CALL_COMPLETE) {
53+
if (!test_bit(RXRPC_CALL_DISCONNECTED, &call->flags)) {
5454
spin_lock_bh(&local->lock);
5555
busy = !list_empty(&call->attend_link);
5656
trace_rxrpc_poke_call(call, busy, what);
@@ -533,13 +533,10 @@ void rxrpc_release_call(struct rxrpc_sock *rx, struct rxrpc_call *call)
533533
trace_rxrpc_call(call->debug_id, refcount_read(&call->ref),
534534
call->flags, rxrpc_call_see_release);
535535

536-
ASSERTCMP(call->state, ==, RXRPC_CALL_COMPLETE);
537-
538536
if (test_and_set_bit(RXRPC_CALL_RELEASED, &call->flags))
539537
BUG();
540538

541539
rxrpc_put_call_slot(call);
542-
del_timer_sync(&call->timer);
543540

544541
/* Make sure we don't get any more notifications */
545542
write_lock(&rx->recvmsg_lock);
@@ -572,10 +569,6 @@ void rxrpc_release_call(struct rxrpc_sock *rx, struct rxrpc_call *call)
572569

573570
_debug("RELEASE CALL %p (%d CONN %p)", call, call->debug_id, conn);
574571

575-
if (conn && !test_bit(RXRPC_CALL_DISCONNECTED, &call->flags))
576-
rxrpc_disconnect_call(call);
577-
if (call->security)
578-
call->security->free_call_crypto(call);
579572
_leave("");
580573
}
581574

net/rxrpc/input.c

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -997,8 +997,6 @@ void rxrpc_input_call_packet(struct rxrpc_call *call, struct sk_buff *skb)
997997
*/
998998
void rxrpc_implicit_end_call(struct rxrpc_call *call, struct sk_buff *skb)
999999
{
1000-
struct rxrpc_connection *conn = call->conn;
1001-
10021000
switch (READ_ONCE(call->state)) {
10031001
case RXRPC_CALL_SERVER_AWAIT_ACK:
10041002
rxrpc_call_completed(call);
@@ -1012,8 +1010,4 @@ void rxrpc_implicit_end_call(struct rxrpc_call *call, struct sk_buff *skb)
10121010
}
10131011

10141012
rxrpc_input_call_event(call, skb);
1015-
1016-
spin_lock(&conn->bundle->channel_lock);
1017-
__rxrpc_disconnect_call(conn, call);
1018-
spin_unlock(&conn->bundle->channel_lock);
10191013
}

net/rxrpc/recvmsg.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@ static void rxrpc_end_rx_phase(struct rxrpc_call *call, rxrpc_serial_t serial)
201201
case RXRPC_CALL_CLIENT_RECV_REPLY:
202202
__rxrpc_call_completed(call);
203203
write_unlock(&call->state_lock);
204+
rxrpc_poke_call(call, rxrpc_call_poke_complete);
204205
break;
205206

206207
case RXRPC_CALL_SERVER_RECV_REQUEST:

0 commit comments

Comments
 (0)