FAILED: patch "[PATCH] rxrpc: Fix call removal to use RCU safe deletion" failed to apply to 5.15-stable tree
Subsystems (4)
[email protected]
maintainerThe patch below does not apply to the 5.15-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-5.15.y
git checkout FETCH_HEAD
git cherry-pick -x 146d4ab94cf129ee06cd467cb5c71368a6b5bad6
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026041333-uncoated-appendix-fea5@gregkh' --subject-prefix 'PATCH 5.15.y' HEAD^..
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 146d4ab94cf129ee06cd467cb5c71368a6b5bad6 Mon Sep 17 00:00:00 2001
From: David Howells <[email protected]>
Date: Wed, 8 Apr 2026 13:12:32 +0100
Subject: [PATCH] rxrpc: Fix call removal to use RCU safe deletion
Fix rxrpc call removal from the rxnet->calls list to use list_del_rcu() rather than list_del_init() to prevent stuffing up reading /proc/net/rxrpc/calls from potentially getting into an infinite loop.
This, however, means that list_empty() no longer works on an entry that's been deleted from the list, making it harder to detect prior deletion. Fix this by:
Firstly, make rxrpc_destroy_all_calls() only dump the first ten calls that are unexpectedly still on the list. Limiting the number of steps means there's no need to call cond_resched() or to remove calls from the list here, thereby eliminating the need for rxrpc_put_call() to check for that.
rxrpc_put_call() can then be fixed to unconditionally delete the call from the list as it is the only place that the deletion occurs.
include/trace/events/rxrpc.h +1 -1
@@ -347,7 +347,7 @@ 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 ") + E_(rxrpc_call_see_still_live, "SEE !still-l")#define rxrpc_txqueue_traces \ EM(rxrpc_txqueue_await_reply, "AWR") \
net/rxrpc/call_object.c +9 -15
@@ -654,11 +654,9 @@ void rxrpc_put_call(struct rxrpc_call *call, enum rxrpc_call_trace why)if (dead) { ASSERTCMP(__rxrpc_call_state(call), ==, RXRPC_CALL_COMPLETE); -if (!list_empty (&call->link)) { -spin_lock (&rxnet->call_lock); -list_del_init (&call->link); -spin_unlock (&rxnet->call_lock); - } +spin_lock (&rxnet->call_lock); +list_del_rcu (&call->link); +spin_unlock (&rxnet->call_lock);rxrpc_cleanup_call (call); }
@@ -730,24 +728,20 @@ void rxrpc_destroy_all_calls(struct rxrpc_net *rxnet)_enter ("" );if (!list_empty (&rxnet->calls)) { +int shown =0 ; +spin_lock (&rxnet->call_lock); -while (!list_empty (&rxnet->calls)) { - call =list_entry (rxnet->calls.next, - struct rxrpc_call, link); -_debug ("Zapping call %p" , call); - -rxrpc_see_call (call, rxrpc_call_see_zap); -list_del_init (&call->link); +list_for_each_entry (call, &rxnet->calls, link) { +rxrpc_see_call (call, rxrpc_call_see_still_live);pr_err ("Call %p still in use (%d,%s,%lx,%lx)!\n" , call,refcount_read (&call->ref), rxrpc_call_states[__rxrpc_call_state (call)], call->flags, call->events); -spin_unlock (&rxnet->call_lock); -cond_resched (); -spin_lock (&rxnet->call_lock); +if (++shown >=10 ) +break ; }spin_unlock (&rxnet->call_lock);
Sasha Levin
maintainerPATCH 1/1 rxrpc: Fix call removal to use RCU safe deletion
From: David Howells <[email protected]>
[ Upstream commit 146d4ab94cf129ee06cd467cb5c71368a6b5bad6 ]
Fix rxrpc call removal from the rxnet->calls list to use list_del_rcu() rather than list_del_init() to prevent stuffing up reading /proc/net/rxrpc/calls from potentially getting into an infinite loop.
This, however, means that list_empty() no longer works on an entry that's been deleted from the list, making it harder to detect prior deletion. Fix this by:
Firstly, make rxrpc_destroy_all_calls() only dump the first ten calls that are unexpectedly still on the list. Limiting the number of steps means there's no need to call cond_resched() or to remove calls from the list here, thereby eliminating the need for rxrpc_put_call() to check for that.
rxrpc_put_call() can then be fixed to unconditionally delete the call from the list as it is the only place that the deletion occurs.
--- net/rxrpc/call_object.c | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-)
net/rxrpc/call_object.c +8 -14
@@ -634,11 +634,9 @@ void rxrpc_put_call(struct rxrpc_call *call, enum rxrpc_call_trace op)_debug ("call %d dead" , call->debug_id); ASSERTCMP(call->state, ==, RXRPC_CALL_COMPLETE); -if (!list_empty (&call->link)) { -spin_lock_bh (&rxnet->call_lock); -list_del_init (&call->link); -spin_unlock_bh (&rxnet->call_lock); - } +spin_lock_bh (&rxnet->call_lock); +list_del_rcu (&call->link); +spin_unlock_bh (&rxnet->call_lock);rxrpc_cleanup_call (call); }
@@ -709,24 +707,20 @@ void rxrpc_destroy_all_calls(struct rxrpc_net *rxnet)_enter ("" );if (!list_empty (&rxnet->calls)) { -spin_lock_bh (&rxnet->call_lock); +int shown =0 ; -while (!list_empty (&rxnet->calls)) { - call =list_entry (rxnet->calls.next, - struct rxrpc_call, link); -_debug ("Zapping call %p" , call); +spin_lock_bh (&rxnet->call_lock); +list_for_each_entry (call, &rxnet->calls, link) {rxrpc_see_call (call); -list_del_init (&call->link);pr_err ("Call %p still in use (%d,%s,%lx,%lx)!\n" , call,refcount_read (&call->ref), rxrpc_call_states[call->state], call->flags, call->events); -spin_unlock_bh (&rxnet->call_lock); -cond_resched (); -spin_lock_bh (&rxnet->call_lock); +if (++shown >=10 ) +break ; }spin_unlock_bh (&rxnet->call_lock);
Signature · 1 line
2.53.0