Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

net: fix backlog_unlock_irq_restore() vs CONFIG_PREEMPT_RT

CONFIG_PREEMPT_RT is special, make this clear in backlog_lock_irq_save()
and backlog_unlock_irq_restore().

The issue shows up with CONFIG_DEBUG_IRQFLAGS=y

raw_local_irq_restore() called with IRQs enabled
WARNING: kernel/locking/irqflag-debug.c:10 at warn_bogus_irq_restore+0xc/0x20 kernel/locking/irqflag-debug.c:10, CPU#1: aoe_tx0/1321
Modules linked in:
CPU: 1 UID: 0 PID: 1321 Comm: aoe_tx0 Not tainted syzkaller #0 PREEMPT_{RT,(full)}
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/24/2026
RIP: 0010:warn_bogus_irq_restore+0xc/0x20 kernel/locking/irqflag-debug.c:10
Call Trace:
<TASK>
backlog_unlock_irq_restore net/core/dev.c:253 [inline]
enqueue_to_backlog+0x525/0xcf0 net/core/dev.c:5347
netif_rx_internal+0x120/0x550 net/core/dev.c:5659
__netif_rx+0xa9/0x110 net/core/dev.c:5679
loopback_xmit+0x43a/0x660 drivers/net/loopback.c:90
__netdev_start_xmit include/linux/netdevice.h:5275 [inline]
netdev_start_xmit include/linux/netdevice.h:5284 [inline]
xmit_one net/core/dev.c:3864 [inline]
dev_hard_start_xmit+0x2df/0x830 net/core/dev.c:3880
__dev_queue_xmit+0x16f4/0x3990 net/core/dev.c:4829
dev_queue_xmit include/linux/netdevice.h:3384 [inline]

Fixes: 27a01c1969a5 ("net: fully inline backlog_unlock_irq_restore()")
Signed-off-by: Eric Dumazet <edumazet@google.com>
Link: https://patch.msgid.link/20260213120427.2914544-1-edumazet@google.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

authored by

Eric Dumazet and committed by
Paolo Abeni
26f29b14 636fd32d

+12 -5
+12 -5
net/core/dev.c
··· 231 231 static inline void backlog_lock_irq_save(struct softnet_data *sd, 232 232 unsigned long *flags) 233 233 { 234 - if (IS_ENABLED(CONFIG_RPS) || use_backlog_threads()) 234 + if (IS_ENABLED(CONFIG_PREEMPT_RT)) { 235 235 spin_lock_irqsave(&sd->input_pkt_queue.lock, *flags); 236 - else 236 + } else { 237 237 local_irq_save(*flags); 238 + if (IS_ENABLED(CONFIG_RPS) || use_backlog_threads()) 239 + spin_lock(&sd->input_pkt_queue.lock); 240 + } 238 241 } 239 242 240 243 static inline void backlog_lock_irq_disable(struct softnet_data *sd) ··· 251 248 static inline void backlog_unlock_irq_restore(struct softnet_data *sd, 252 249 unsigned long flags) 253 250 { 254 - if (IS_ENABLED(CONFIG_RPS) || use_backlog_threads()) 255 - spin_unlock(&sd->input_pkt_queue.lock); 256 - local_irq_restore(flags); 251 + if (IS_ENABLED(CONFIG_PREEMPT_RT)) { 252 + spin_unlock_irqrestore(&sd->input_pkt_queue.lock, flags); 253 + } else { 254 + if (IS_ENABLED(CONFIG_RPS) || use_backlog_threads()) 255 + spin_unlock(&sd->input_pkt_queue.lock); 256 + local_irq_restore(flags); 257 + } 257 258 } 258 259 259 260 static inline void backlog_unlock_irq_enable(struct softnet_data *sd)