[PATCH 6.6 048/119] rxrpc: Fix missing locking causing hanging calls
Greg Kroah-Hartman
gregkh at linuxfoundation.org
Tue Nov 12 02:20:56 PST 2024
6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Howells <dhowells at redhat.com>
[ Upstream commit fc9de52de38f656399d2ce40f7349a6b5f86e787 ]
If a call gets aborted (e.g. because kafs saw a signal) between it being
queued for connection and the I/O thread picking up the call, the abort
will be prioritised over the connection and it will be removed from
local->new_client_calls by rxrpc_disconnect_client_call() without a lock
being held. This may cause other calls on the list to disappear if a race
occurs.
Fix this by taking the client_call_lock when removing a call from whatever
list its ->wait_link happens to be on.
Signed-off-by: David Howells <dhowells at redhat.com>
cc: linux-afs at lists.infradead.org
Reported-by: Marc Dionne <marc.dionne at auristor.com>
Fixes: 9d35d880e0e4 ("rxrpc: Move client call connection to the I/O thread")
Link: https://patch.msgid.link/726660.1730898202@warthog.procyon.org.uk
Signed-off-by: Jakub Kicinski <kuba at kernel.org>
Signed-off-by: Sasha Levin <sashal at kernel.org>
---
include/trace/events/rxrpc.h | 1 +
net/rxrpc/conn_client.c | 4 ++++
2 files changed, 5 insertions(+)
diff --git a/include/trace/events/rxrpc.h b/include/trace/events/rxrpc.h
index 3322fb93a260b..ed36f5f577a9d 100644
--- a/include/trace/events/rxrpc.h
+++ b/include/trace/events/rxrpc.h
@@ -283,6 +283,7 @@
EM(rxrpc_call_see_input, "SEE input ") \
EM(rxrpc_call_see_release, "SEE release ") \
EM(rxrpc_call_see_userid_exists, "SEE u-exists") \
+ EM(rxrpc_call_see_waiting_call, "SEE q-conn ") \
E_(rxrpc_call_see_zap, "SEE zap ")
#define rxrpc_txqueue_traces \
diff --git a/net/rxrpc/conn_client.c b/net/rxrpc/conn_client.c
index 1d95f8bc769fa..a0231b64fb6ef 100644
--- a/net/rxrpc/conn_client.c
+++ b/net/rxrpc/conn_client.c
@@ -507,6 +507,7 @@ void rxrpc_connect_client_calls(struct rxrpc_local *local)
spin_lock(&local->client_call_lock);
list_move_tail(&call->wait_link, &bundle->waiting_calls);
+ rxrpc_see_call(call, rxrpc_call_see_waiting_call);
spin_unlock(&local->client_call_lock);
if (rxrpc_bundle_has_space(bundle))
@@ -577,7 +578,10 @@ void rxrpc_disconnect_client_call(struct rxrpc_bundle *bundle, struct rxrpc_call
_debug("call is waiting");
ASSERTCMP(call->call_id, ==, 0);
ASSERT(!test_bit(RXRPC_CALL_EXPOSED, &call->flags));
+ /* May still be on ->new_client_calls. */
+ spin_lock(&local->client_call_lock);
list_del_init(&call->wait_link);
+ spin_unlock(&local->client_call_lock);
return;
}
--
2.43.0
More information about the linux-afs
mailing list