[PATCH net-next 08/32] rxrpc: Only disconnect calls in the I/O thread
From: David Howells
Date: Tue Dec 06 2022 - 11:01:44 EST
Only perform call disconnection in the I/O thread to reduce the locking
requirement.
Signed-off-by: David Howells <dhowells@xxxxxxxxxx>
cc: Marc Dionne <marc.dionne@xxxxxxxxxxxx>
cc: linux-afs@xxxxxxxxxxxxxxxxxxx
---
include/trace/events/rxrpc.h | 1 +
net/rxrpc/call_event.c | 14 +++++++++++++-
net/rxrpc/call_object.c | 9 +--------
net/rxrpc/input.c | 1 -
net/rxrpc/recvmsg.c | 1 +
5 files changed, 16 insertions(+), 10 deletions(-)
diff --git a/include/trace/events/rxrpc.h b/include/trace/events/rxrpc.h
index 72f020b829e0..49a0f799cdef 100644
--- a/include/trace/events/rxrpc.h
+++ b/include/trace/events/rxrpc.h
@@ -18,6 +18,7 @@
*/
#define rxrpc_call_poke_traces \
EM(rxrpc_call_poke_abort, "Abort") \
+ EM(rxrpc_call_poke_complete, "Compl") \
EM(rxrpc_call_poke_error, "Error") \
EM(rxrpc_call_poke_idle, "Idle") \
EM(rxrpc_call_poke_start, "Start") \
diff --git a/net/rxrpc/call_event.c b/net/rxrpc/call_event.c
index a8b5dff09999..bf6858e69187 100644
--- a/net/rxrpc/call_event.c
+++ b/net/rxrpc/call_event.c
@@ -347,6 +347,13 @@ void rxrpc_input_call_event(struct rxrpc_call *call, struct sk_buff *skb)
if (call->state == RXRPC_CALL_COMPLETE)
goto out;
+ if (!call->conn) {
+ printk("\n");
+ printk("\n");
+ kdebug("no conn %u", call->state);
+ printk("\n");
+ }
+
abort_code = smp_load_acquire(&call->send_abort);
if (abort_code)
rxrpc_abort_call(call->send_abort_why, call, 0, call->send_abort,
@@ -479,8 +486,13 @@ void rxrpc_input_call_event(struct rxrpc_call *call, struct sk_buff *skb)
}
out:
- if (call->state == RXRPC_CALL_COMPLETE)
+ if (call->state == RXRPC_CALL_COMPLETE) {
del_timer_sync(&call->timer);
+ if (!test_bit(RXRPC_CALL_DISCONNECTED, &call->flags))
+ rxrpc_disconnect_call(call);
+ if (call->security)
+ call->security->free_call_crypto(call);
+ }
if (call->acks_hard_ack != call->tx_bottom)
rxrpc_shrink_call_tx_buffer(call);
_leave("");
diff --git a/net/rxrpc/call_object.c b/net/rxrpc/call_object.c
index f7606cdf4209..a9c77be9107a 100644
--- a/net/rxrpc/call_object.c
+++ b/net/rxrpc/call_object.c
@@ -50,7 +50,7 @@ void rxrpc_poke_call(struct rxrpc_call *call, enum rxrpc_call_poke_trace what)
struct rxrpc_local *local = call->local;
bool busy;
- if (call->state < RXRPC_CALL_COMPLETE) {
+ if (!test_bit(RXRPC_CALL_DISCONNECTED, &call->flags)) {
spin_lock_bh(&local->lock);
busy = !list_empty(&call->attend_link);
trace_rxrpc_poke_call(call, busy, what);
@@ -529,13 +529,10 @@ void rxrpc_release_call(struct rxrpc_sock *rx, struct rxrpc_call *call)
trace_rxrpc_call(call->debug_id, refcount_read(&call->ref),
call->flags, rxrpc_call_see_release);
- ASSERTCMP(call->state, ==, RXRPC_CALL_COMPLETE);
-
if (test_and_set_bit(RXRPC_CALL_RELEASED, &call->flags))
BUG();
rxrpc_put_call_slot(call);
- del_timer_sync(&call->timer);
/* Make sure we don't get any more notifications */
spin_lock(&rx->recvmsg_lock);
@@ -568,10 +565,6 @@ void rxrpc_release_call(struct rxrpc_sock *rx, struct rxrpc_call *call)
_debug("RELEASE CALL %p (%d CONN %p)", call, call->debug_id, conn);
- if (conn && !test_bit(RXRPC_CALL_DISCONNECTED, &call->flags))
- rxrpc_disconnect_call(call);
- if (call->security)
- call->security->free_call_crypto(call);
_leave("");
}
diff --git a/net/rxrpc/input.c b/net/rxrpc/input.c
index 58077b5bfb68..a72fd2f78fc0 100644
--- a/net/rxrpc/input.c
+++ b/net/rxrpc/input.c
@@ -1010,5 +1010,4 @@ void rxrpc_implicit_end_call(struct rxrpc_call *call, struct sk_buff *skb)
}
rxrpc_input_call_event(call, skb);
- rxrpc_disconnect_call(call);
}
diff --git a/net/rxrpc/recvmsg.c b/net/rxrpc/recvmsg.c
index 492608973935..88298ab8a9d7 100644
--- a/net/rxrpc/recvmsg.c
+++ b/net/rxrpc/recvmsg.c
@@ -202,6 +202,7 @@ static void rxrpc_end_rx_phase(struct rxrpc_call *call, rxrpc_serial_t serial)
case RXRPC_CALL_CLIENT_RECV_REPLY:
__rxrpc_call_completed(call);
spin_unlock(&call->state_lock);
+ rxrpc_poke_call(call, rxrpc_call_poke_complete);
break;
case RXRPC_CALL_SERVER_RECV_REQUEST: