Skip to content

Commit e4d2878

Browse files
dhowellskuba-moo
authored andcommitted
rxrpc: Fix irq-disabled in local_bh_enable()
The rxrpc_assess_MTU_size() function calls down into the IP layer to find out the MTU size for a route. When accepting an incoming call, this is called from rxrpc_new_incoming_call() which holds interrupts disabled across the code that calls down to it. Unfortunately, the IP layer uses local_bh_enable() which, config dependent, throws a warning if IRQs are enabled: WARNING: CPU: 1 PID: 5544 at kernel/softirq.c:387 __local_bh_enable_ip+0x43/0xd0 ... RIP: 0010:__local_bh_enable_ip+0x43/0xd0 ... Call Trace: <TASK> rt_cache_route+0x7e/0xa0 rt_set_nexthop.isra.0+0x3b3/0x3f0 __mkroute_output+0x43a/0x460 ip_route_output_key_hash+0xf7/0x140 ip_route_output_flow+0x1b/0x90 rxrpc_assess_MTU_size.isra.0+0x2a0/0x590 rxrpc_new_incoming_peer+0x46/0x120 rxrpc_alloc_incoming_call+0x1b1/0x400 rxrpc_new_incoming_call+0x1da/0x5e0 rxrpc_input_packet+0x827/0x900 rxrpc_io_thread+0x403/0xb60 kthread+0x2f7/0x310 ret_from_fork+0x2a/0x230 ret_from_fork_asm+0x1a/0x30 ... hardirqs last enabled at (23): _raw_spin_unlock_irq+0x24/0x50 hardirqs last disabled at (24): _raw_read_lock_irq+0x17/0x70 softirqs last enabled at (0): copy_process+0xc61/0x2730 softirqs last disabled at (25): rt_add_uncached_list+0x3c/0x90 Fix this by moving the call to rxrpc_assess_MTU_size() out of rxrpc_init_peer() and further up the stack where it can be done without interrupts disabled. It shouldn't be a problem for rxrpc_new_incoming_call() to do it after the locks are dropped as pmtud is going to be performed by the I/O thread - and we're in the I/O thread at this point. Fixes: a2ea9a9 ("rxrpc: Use irq-disabling spinlocks between app and I/O thread") Signed-off-by: David Howells <[email protected]> Reviewed-by: Jeffrey Altman <[email protected]> cc: Marc Dionne <[email protected]> cc: Junvyyang, Tencent Zhuque Lab <[email protected]> cc: LePremierHomme <[email protected]> cc: Simon Horman <[email protected]> cc: [email protected] Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 88b06e4 commit e4d2878

File tree

3 files changed

+4
-4
lines changed

3 files changed

+4
-4
lines changed

net/rxrpc/ar-internal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1383,6 +1383,7 @@ struct rxrpc_peer *rxrpc_lookup_peer_rcu(struct rxrpc_local *,
13831383
const struct sockaddr_rxrpc *);
13841384
struct rxrpc_peer *rxrpc_lookup_peer(struct rxrpc_local *local,
13851385
struct sockaddr_rxrpc *srx, gfp_t gfp);
1386+
void rxrpc_assess_MTU_size(struct rxrpc_local *local, struct rxrpc_peer *peer);
13861387
struct rxrpc_peer *rxrpc_alloc_peer(struct rxrpc_local *, gfp_t,
13871388
enum rxrpc_peer_trace);
13881389
void rxrpc_new_incoming_peer(struct rxrpc_local *local, struct rxrpc_peer *peer);

net/rxrpc/call_accept.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,7 @@ bool rxrpc_new_incoming_call(struct rxrpc_local *local,
406406

407407
spin_unlock(&rx->incoming_lock);
408408
read_unlock_irq(&local->services_lock);
409+
rxrpc_assess_MTU_size(local, call->peer);
409410

410411
if (hlist_unhashed(&call->error_link)) {
411412
spin_lock_irq(&call->peer->lock);

net/rxrpc/peer_object.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -149,8 +149,7 @@ struct rxrpc_peer *rxrpc_lookup_peer_rcu(struct rxrpc_local *local,
149149
* assess the MTU size for the network interface through which this peer is
150150
* reached
151151
*/
152-
static void rxrpc_assess_MTU_size(struct rxrpc_local *local,
153-
struct rxrpc_peer *peer)
152+
void rxrpc_assess_MTU_size(struct rxrpc_local *local, struct rxrpc_peer *peer)
154153
{
155154
struct net *net = local->net;
156155
struct dst_entry *dst;
@@ -277,8 +276,6 @@ static void rxrpc_init_peer(struct rxrpc_local *local, struct rxrpc_peer *peer,
277276

278277
peer->hdrsize += sizeof(struct rxrpc_wire_header);
279278
peer->max_data = peer->if_mtu - peer->hdrsize;
280-
281-
rxrpc_assess_MTU_size(local, peer);
282279
}
283280

284281
/*
@@ -297,6 +294,7 @@ static struct rxrpc_peer *rxrpc_create_peer(struct rxrpc_local *local,
297294
if (peer) {
298295
memcpy(&peer->srx, srx, sizeof(*srx));
299296
rxrpc_init_peer(local, peer, hash_key);
297+
rxrpc_assess_MTU_size(local, peer);
300298
}
301299

302300
_leave(" = %p", peer);

0 commit comments

Comments
 (0)