* [syzbot] [bridge?] WARNING: locking bug in match_held_lock
@ 2026-09-13 1:31 syzbot
2026-09-15 3:40 ` Shin'ichiro Kawasaki
0 siblings, 1 reply; 7+ messages in thread
From: syzbot @ 2026-09-13 1:31 UTC (permalink / raw)
To: bridge, davem, edumazet, herbert, horms, idosch, kuba,
linux-kernel, netdev, pabeni, razor, steffen.klassert,
syzkaller-bugs
Hello,
syzbot found the following issue on:
HEAD commit: a9d7ced84989 Add linux-next specific files for 20260908
git tree: linux-next
console output: https://syzkaller.appspot.com/x/log.txt?x=10880f49580000
kernel config: https://syzkaller.appspot.com/x/.config?x=17eeb09695a2b3c9
dashboard link: https://syzkaller.appspot.com/bug?extid=4d0e4d2db6dfde01b52f
compiler: Debian clang version 22.1.8 (++20260613092233+e80beda6e255-1~exp1~20260613092250.77), Debian LLD 22.1.8
Unfortunately, I don't have any reproducer for this issue yet.
Downloadable assets:
disk image: https://storage.googleapis.com/syzbot-assets/4f470407358e/disk-a9d7ced8.raw.xz
vmlinux: https://storage.googleapis.com/syzbot-assets/858b9d7ba687/vmlinux-a9d7ced8.xz
kernel image: https://storage.googleapis.com/syzbot-assets/ef971d22d75f/bzImage-a9d7ced8.xz
IMPORTANT: if you fix the issue, please add the following tag to the commit:
Reported-by: syzbot+4d0e4d2db6dfde01b52f@syzkaller.appspotmail.com
------------[ cut here ]------------
Looking for class "&ht->mutex" with key xfrm_policy_init.__key.84, but found a different class "key" with the same key
WARNING: kernel/locking/lockdep.c:958 at look_up_lock_class+0x8c/0x110 kernel/locking/lockdep.c:955, CPU#1: kworker/1:6/5751
Modules linked in:
CPU: 1 UID: 0 PID: 5751 Comm: kworker/1:6 Tainted: G L syzkaller #0 PREEMPT(full)
Tainted: [L]=SOFTLOCKUP
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 07/24/2026
Workqueue: usb_hub_wq hub_event
RIP: 0010:look_up_lock_class+0x9a/0x110 kernel/locking/lockdep.c:955
Code: 00 00 49 3b 46 18 0f 84 82 00 00 00 49 81 3e d0 44 58 94 74 79 48 8d 3d 44 f2 94 04 49 8b 16 49 8b 76 18 48 8b 8b b8 00 00 00 <67> 48 0f b9 3a eb 5d 90 89 f3 e8 67 0a f4 f8 e8 32 5c be f5 48 c7
RSP: 0018:ffffc90000a38070 EFLAGS: 00010002
RAX: ffffffff8c6bb940 RBX: ffffffff94478508 RCX: ffffffff8c6bb940
RDX: ffffffff9af23440 RSI: ffffffff8c6bb900 RDI: ffffffff907ddb20
RBP: 00000000ffffffff R08: 0000000000000100 R09: 0000000000000004
R10: 0000000000000003 R11: 0000000000000300 R12: 0000000000000246
R13: ffff8880307a8000 R14: ffffffff9af232c8 R15: ffffffff9af23440
FS: 0000000000000000(0000) GS:ffff888124db7000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000001b3401aff8 CR3: 0000000074540000 CR4: 00000000003526f0
Call Trace:
<IRQ>
match_held_lock+0x9a/0x120 kernel/locking/lockdep.c:5364
__lock_is_held kernel/locking/lockdep.c:5654 [inline]
lock_is_held_type+0x89/0x150 kernel/locking/lockdep.c:6016
__rhashtable_lookup include/linux/rhashtable.h:623 [inline]
rhashtable_lookup include/linux/rhashtable.h:668 [inline]
xfrm_policy_inexact_lookup_rcu+0x60/0x750 net/xfrm/xfrm_policy.c:2068
xfrm_policy_lookup_bytype+0xb35/0x1840 net/xfrm/xfrm_policy.c:2193
xfrm_policy_lookup net/xfrm/xfrm_policy.c:2225 [inline]
xfrm_bundle_lookup net/xfrm/xfrm_policy.c:3100 [inline]
xfrm_lookup_with_ifid+0x416/0x1db0 net/xfrm/xfrm_policy.c:3241
xfrmi_xmit2 net/xfrm/xfrm_interface_core.c:456 [inline]
xfrmi_xmit+0x72d/0x1b80 net/xfrm/xfrm_interface_core.c:572
__netdev_start_xmit include/linux/netdevice.h:5433 [inline]
netdev_start_xmit include/linux/netdevice.h:5442 [inline]
xmit_one net/core/dev.c:3937 [inline]
dev_hard_start_xmit+0x2cd/0x830 net/core/dev.c:3953
__dev_queue_xmit+0x14c0/0x3820 net/core/dev.c:4926
NF_HOOK_COND include/linux/netfilter.h:314 [inline]
ip6_output+0x337/0x540 net/ipv6/ip6_output.c:248
dst_output include/net/dst.h:471 [inline]
NF_HOOK include/linux/netfilter.h:325 [inline]
ndisc_send_skb+0xcb2/0x1650 net/ipv6/ndisc.c:513
addrconf_rs_timer+0x2d2/0x6c0 net/ipv6/addrconf.c:4078
call_timer_fn+0x18d/0x5f0 kernel/time/timer.c:1748
expire_timers kernel/time/timer.c:1799 [inline]
__run_timers kernel/time/timer.c:2374 [inline]
__run_timer_base+0x652/0x8b0 kernel/time/timer.c:2386
run_timer_base kernel/time/timer.c:2395 [inline]
run_timer_softirq+0xb7/0x170 kernel/time/timer.c:2405
handle_softirqs+0x223/0x840 kernel/softirq.c:645
__do_softirq kernel/softirq.c:679 [inline]
invoke_softirq kernel/softirq.c:519 [inline]
__irq_exit_rcu+0xcb/0x220 kernel/softirq.c:758
irq_exit_rcu+0x9/0x30 kernel/softirq.c:775
instr_sysvec_apic_timer_interrupt arch/x86/kernel/apic/apic.c:1062 [inline]
sysvec_apic_timer_interrupt+0xa6/0xc0 arch/x86/kernel/apic/apic.c:1062
</IRQ>
<TASK>
asm_sysvec_apic_timer_interrupt+0x1a/0x20 arch/x86/include/asm/idtentry.h:674
RIP: 0010:finish_task_switch+0x413/0xc60 kernel/sched/core.c:5378
Code: 04 00 00 41 c7 84 24 20 0e 00 00 00 00 00 00 0f 1f 44 00 00 49 83 c4 48 4c 89 e7 e8 57 48 55 0a e8 d2 1b 3a 00 fb 4c 8b 65 c8 <49> 8d bc 24 10 17 00 00 48 89 f8 48 c1 e8 03 42 0f b6 04 30 84 c0
RSP: 0018:ffffc900043ad940 EFLAGS: 00000206
RAX: 000000000004ba5f RBX: ffff8880b873cb20 RCX: 8000000000000001
RDX: 0000000000000006 RSI: ffffffff8e47d8da RDI: ffffffff8c6dc080
RBP: ffffc900043ad990 R08: ffffffff907a9cbf R09: 1ffffffff20f5397
R10: dffffc0000000000 R11: fffffbfff20f5398 R12: ffff8880307a8000
R13: ffff8880b873cae8 R14: dffffc0000000000 R15: 1ffff110170e7964
context_switch kernel/sched/core.c:5530 [inline]
__schedule+0x17e5/0x5940 kernel/sched/core.c:7295
preempt_schedule_common+0x7f/0xd0 kernel/sched/core.c:7474
preempt_schedule_thunk+0x16/0x40 arch/x86/entry/thunk.S:12
__mutex_lock_common kernel/locking/mutex.c:656 [inline]
__mutex_lock+0x31b/0x15a0 kernel/locking/mutex.c:821
clear_eld drivers/gpu/drm/drm_edid.c:5691 [inline]
update_display_info+0x455/0x9630 drivers/gpu/drm/drm_edid.c:6934
drm_edid_connector_update+0x9b/0x13d0 drivers/gpu/drm/drm_edid.c:7338
drm_connector_update_edid_property+0xde/0x140 drivers/gpu/drm/drm_edid.c:7396
drm_helper_probe_single_connector_modes+0x126b/0x1880 drivers/gpu/drm/drm_probe_helper.c:644
drm_client_modeset_probe+0x4e8/0x60c0 drivers/gpu/drm/drm_client_modeset.c:869
__drm_fb_helper_initial_config_and_unlock+0x10e/0x1b50 drivers/gpu/drm/drm_fb_helper.c:1717
drm_fbdev_client_hotplug+0x16c/0x230 drivers/gpu/drm/clients/drm_fbdev_client.c:66
drm_client_register+0x16e/0x200 drivers/gpu/drm/drm_client.c:143
drm_fbdev_client_setup+0x1a0/0x450 drivers/gpu/drm/clients/drm_fbdev_client.c:168
drm_client_setup+0x107/0x220 drivers/gpu/drm/clients/drm_client_setup.c:46
udl_usb_probe+0x137/0x150 drivers/gpu/drm/udl/udl_drv.c:105
usb_probe_interface+0x788/0xe50 drivers/usb/core/driver.c:399
call_driver_probe drivers/base/dd.c:-1 [inline]
really_probe+0x254/0xae0 drivers/base/dd.c:706
__driver_probe_device+0x1e8/0x360 drivers/base/dd.c:868
driver_probe_device+0x4f/0x240 drivers/base/dd.c:898
__device_attach_driver+0x270/0x410 drivers/base/dd.c:1026
bus_for_each_drv+0x258/0x2f0 drivers/base/bus.c:500
__device_attach+0x2c4/0x450 drivers/base/dd.c:1098
device_initial_probe+0xa1/0xd0 drivers/base/dd.c:1153
bus_probe_device+0x12a/0x220 drivers/base/bus.c:620
device_add+0x7d7/0xb80 drivers/base/core.c:3776
usb_set_configuration+0x1ad8/0x2180 drivers/usb/core/message.c:2268
usb_generic_driver_probe+0x8d/0x150 drivers/usb/core/generic.c:250
usb_probe_device+0x1c3/0x3b0 drivers/usb/core/driver.c:293
call_driver_probe drivers/base/dd.c:-1 [inline]
really_probe+0x254/0xae0 drivers/base/dd.c:706
__driver_probe_device+0x1e8/0x360 drivers/base/dd.c:868
driver_probe_device+0x4f/0x240 drivers/base/dd.c:898
__device_attach_driver+0x270/0x410 drivers/base/dd.c:1026
bus_for_each_drv+0x258/0x2f0 drivers/base/bus.c:500
__device_attach+0x2c4/0x450 drivers/base/dd.c:1098
device_initial_probe+0xa1/0xd0 drivers/base/dd.c:1153
bus_probe_device+0x12a/0x220 drivers/base/bus.c:620
device_add+0x7d7/0xb80 drivers/base/core.c:3776
usb_new_device+0x9aa/0x1690 drivers/usb/core/hub.c:2708
hub_port_connect drivers/usb/core/hub.c:5580 [inline]
hub_port_connect_change drivers/usb/core/hub.c:5720 [inline]
port_event drivers/usb/core/hub.c:5884 [inline]
hub_event+0x28e8/0x4d30 drivers/usb/core/hub.c:5966
process_one_work kernel/workqueue.c:3407 [inline]
process_scheduled_works+0xc3d/0x1630 kernel/workqueue.c:3490
worker_thread+0xa47/0xfb0 kernel/workqueue.c:3571
kthread+0x38b/0x480 kernel/kthread.c:436
ret_from_fork+0x514/0xb70 arch/x86/kernel/process.c:158
ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
</TASK>
----------------
Code disassembly (best guess):
0: 00 00 add %al,(%rax)
2: 49 3b 46 18 cmp 0x18(%r14),%rax
6: 0f 84 82 00 00 00 je 0x8e
c: 49 81 3e d0 44 58 94 cmpq $0xffffffff945844d0,(%r14)
13: 74 79 je 0x8e
15: 48 8d 3d 44 f2 94 04 lea 0x494f244(%rip),%rdi # 0x494f260
1c: 49 8b 16 mov (%r14),%rdx
1f: 49 8b 76 18 mov 0x18(%r14),%rsi
23: 48 8b 8b b8 00 00 00 mov 0xb8(%rbx),%rcx
* 2a: 67 48 0f b9 3a ud1 (%edx),%rdi <-- trapping instruction
2f: eb 5d jmp 0x8e
31: 90 nop
32: 89 f3 mov %esi,%ebx
34: e8 67 0a f4 f8 call 0xf8f40aa0
39: e8 32 5c be f5 call 0xf5be5c70
3e: 48 rex.W
3f: c7 .byte 0xc7
---
This report is generated by a bot. It may contain errors.
See https://goo.gl/tpsmEJ for more information about syzbot.
syzbot engineers can be reached at syzkaller@googlegroups.com.
syzbot will keep track of this issue. See:
https://goo.gl/tpsmEJ#status for how to communicate with syzbot.
If the report is already addressed, let syzbot know by replying with:
#syz fix: exact-commit-title
If you want to overwrite report's subsystems, reply with:
#syz set subsystems: new-subsystem
(See the list of subsystem names on the web dashboard)
If the report is a duplicate of another one, reply with:
#syz dup: exact-subject-of-another-report
If you want to undo deduplication, reply with:
#syz undup
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [syzbot] [bridge?] WARNING: locking bug in match_held_lock
2026-09-13 1:31 [syzbot] [bridge?] WARNING: locking bug in match_held_lock syzbot
@ 2026-09-15 3:40 ` Shin'ichiro Kawasaki
2026-09-15 4:06 ` Eric Dumazet
0 siblings, 1 reply; 7+ messages in thread
From: Shin'ichiro Kawasaki @ 2026-09-15 3:40 UTC (permalink / raw)
To: syzbot
Cc: bridge, davem, edumazet, herbert, horms, idosch, kuba,
linux-kernel, netdev, pabeni, razor, steffen.klassert,
syzkaller-bugs, Thomas Graf, linux-crypto
CC+: linux-crypto and rhashtable maintainers,
On Sep 12, 2026 / 18:31, syzbot wrote:
> Hello,
>
> syzbot found the following issue on:
>
> HEAD commit: a9d7ced84989 Add linux-next specific files for 20260908
> git tree: linux-next
> console output: https://syzkaller.appspot.com/x/log.txt?x=10880f49580000
> kernel config: https://syzkaller.appspot.com/x/.config?x=17eeb09695a2b3c9
> dashboard link: https://syzkaller.appspot.com/bug?extid=4d0e4d2db6dfde01b52f
> compiler: Debian clang version 22.1.8 (++20260613092233+e80beda6e255-1~exp1~20260613092250.77), Debian LLD 22.1.8
>
> Unfortunately, I don't have any reproducer for this issue yet.
>
> Downloadable assets:
> disk image: https://storage.googleapis.com/syzbot-assets/4f470407358e/disk-a9d7ced8.raw.xz
> vmlinux: https://storage.googleapis.com/syzbot-assets/858b9d7ba687/vmlinux-a9d7ced8.xz
> kernel image: https://storage.googleapis.com/syzbot-assets/ef971d22d75f/bzImage-a9d7ced8.xz
>
> IMPORTANT: if you fix the issue, please add the following tag to the commit:
> Reported-by: syzbot+4d0e4d2db6dfde01b52f@syzkaller.appspotmail.com
>
> ------------[ cut here ]------------
> Looking for class "&ht->mutex" with key xfrm_policy_init.__key.84, but found a different class "key" with the same key
> WARNING: kernel/locking/lockdep.c:958 at look_up_lock_class+0x8c/0x110 kernel/locking/lockdep.c:955, CPU#1: kworker/1:6/5751
> Modules linked in:
> CPU: 1 UID: 0 PID: 5751 Comm: kworker/1:6 Tainted: G L syzkaller #0 PREEMPT(full)
> Tainted: [L]=SOFTLOCKUP
> Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 07/24/2026
> Workqueue: usb_hub_wq hub_event
> RIP: 0010:look_up_lock_class+0x9a/0x110 kernel/locking/lockdep.c:955
> Code: 00 00 49 3b 46 18 0f 84 82 00 00 00 49 81 3e d0 44 58 94 74 79 48 8d 3d 44 f2 94 04 49 8b 16 49 8b 76 18 48 8b 8b b8 00 00 00 <67> 48 0f b9 3a eb 5d 90 89 f3 e8 67 0a f4 f8 e8 32 5c be f5 48 c7
> RSP: 0018:ffffc90000a38070 EFLAGS: 00010002
> RAX: ffffffff8c6bb940 RBX: ffffffff94478508 RCX: ffffffff8c6bb940
> RDX: ffffffff9af23440 RSI: ffffffff8c6bb900 RDI: ffffffff907ddb20
> RBP: 00000000ffffffff R08: 0000000000000100 R09: 0000000000000004
> R10: 0000000000000003 R11: 0000000000000300 R12: 0000000000000246
> R13: ffff8880307a8000 R14: ffffffff9af232c8 R15: ffffffff9af23440
> FS: 0000000000000000(0000) GS:ffff888124db7000(0000) knlGS:0000000000000000
> CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> CR2: 0000001b3401aff8 CR3: 0000000074540000 CR4: 00000000003526f0
> Call Trace:
> <IRQ>
> match_held_lock+0x9a/0x120 kernel/locking/lockdep.c:5364
> __lock_is_held kernel/locking/lockdep.c:5654 [inline]
> lock_is_held_type+0x89/0x150 kernel/locking/lockdep.c:6016
> __rhashtable_lookup include/linux/rhashtable.h:623 [inline]
> rhashtable_lookup include/linux/rhashtable.h:668 [inline]
> xfrm_policy_inexact_lookup_rcu+0x60/0x750 net/xfrm/xfrm_policy.c:2068
> xfrm_policy_lookup_bytype+0xb35/0x1840 net/xfrm/xfrm_policy.c:2193
...
FYI, I also observed the WARN at look_up_lock_class() and match_held_lock()
called in the rhashtable_lookup() context [1]. I used the kernel next-20260909.
The WARN was observed during the run of blktests test case block/008 on dm-
flakey device, but this test workload does not look related to the WARN. I tried
to reproduce the WARN by repeating the test workload hundreds of times, and
succeeded only once. The WARN looks rare, but I'm sure the WARN happned.
The call trace that syzbot reported and that I observed look rather different.
The common part across them is the rhashtable_lookup() call. So I think it is
the better to involve rhashtable experts. I took the liberty CC to them.
[1] WARN observed at blktests block/008 for dm-flakey
WARNING: kernel/locking/lockdep.c:955 at look_up_lock_class+0xa8/0x170, CPU#14: kworker/14:1/309662
Modules linked in: dm_flakey iscsi_target_mod tcm_loop target_core_pscsi target_core_file target_core_iblock xfs target_core_user target_core_mod nft_fib_inet nft_fib_ipv4 nft_fib_ipv6 nft_fib nft_reject_inet nf_reject_ipv4 nf_reject_ipv6 nft_reject qrtr nft_ct nft_chain_nat ip6table_nat ip6table_mangle ip6table_raw ip6table_security iptable_nat nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 iptable_mangle rfkill iptable_raw iptable_security nf_tables ip6table_filter ip6_tables iptable_filter ip_tables irdma ice sunrpc libie_fwlog gnss idpf libeth_xdp libie_pci libie_cp libeth ib_core intel_rapl_msr intel_rapl_common intel_uncore_frequency intel_uncore_frequency_common skx_edac skx_edac_common nfit libnvdimm x86_pkg_temp_thermal intel_powerclamp coretemp kvm_intel spi_nor mtd kvm i40e irqbypass iTCO_wdt rapl intel_pmc_bxt vfat ses intel_cstate libie fat intel_uncore libie_adminq enclosure i2c_i801 spi_intel_pci spi_intel i2c_smbus lpc_ich mei_me mei intel_pch_thermal wmi joydev ioatdma acpi_pad
acpi_power_meter dca fuse dm_multipath zram lz4hc_compress zstd_compress ast drm_client_lib i2c_algo_bit drm_shmem_helper drm_kms_helper nvme drm nvme_core mpi3mr nvme_keyring nvme_auth scsi_transport_sas scsi_dh_alua pkcs8_key_parser scsi_dh_emc scsi_dh_rdac i2c_dev [last unloaded: null_blk]
CPU: 14 UID: 0 PID: 309662 Comm: kworker/14:1 Tainted: G W 7.3.0-rc2-next-20260909-kts+ #1 PREEMPT(lazy)
Tainted: [W]=WARN
Hardware name: Supermicro Super Server/X11SPi-TF, BIOS 3.5 05/18/2021
Workqueue: events drm_fb_helper_damage_work [drm_kms_helper]
RIP: 0010:look_up_lock_class+0xa8/0x170
Code: 39 6b 40 75 ed 48 8b 8b b8 00 00 00 49 8b 74 24 18 48 39 f1 74 34 49 8b 14 24 48 81 fa f0 31 7f 9a 74 27 48 8d 3d b8 66 4a 02 <67> 48 0f b9 3a 48 89 d8 48 8b 6c 24 10 4c 8b 64 24 18 48 8b 5c 24
RSP: 0018:ffff888e40108088 EFLAGS: 00010002
RAX: 0000000000000001 RBX: ffffffff9e852a78 RCX: ffffffff97838ae0
RDX: ffffffffc271a2a0 RSI: ffffffff97838a60 RDI: ffffffff997aa470
RBP: ffffffffc271a2a0 R08: 0000000000000001 R09: ffff888133ab3018
R10: 0000000000000004 R11: ffff888e40108360 R12: ffff88812d59e1f8
R13: 0000000000000003 R14: 0000000000000246 R15: 00000000ffffffff
FS: 0000000000000000(0000) GS:ffff888ea59d3000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 000055dba25b8c90 CR3: 00000002a6911004 CR4: 00000000007726f0
PKRU: 55555554
Call Trace:
<IRQ>
match_held_lock+0xdb/0x130
lock_is_held_type+0xb0/0x180
nft_rhash_lookup+0x541/0x7e0 [nf_tables]
? find_held_lock+0x2b/0x80
? __lock_release.isra.0+0x69/0x1a0
? lock_release.part.0+0x1c/0x50
? __pfx_nft_rhash_lookup+0x10/0x10 [nf_tables]
nft_set_do_lookup+0x1ac/0x2a0 [nf_tables]
? fib_lookup_good_nhc+0x104/0x380
nft_lookup_eval+0xcc/0x590 [nf_tables]
? lock_is_held_type+0xb0/0x180
nft_do_chain+0x2a9/0x1680 [nf_tables]
? __lock_acquire+0x690/0xd00
? __pfx_nft_do_chain+0x10/0x10 [nf_tables]
? lock_acquire.part.0+0xc8/0x240
? find_held_lock+0x2b/0x80
? __local_bh_enable_ip+0xb4/0x150
? ipt_do_table+0xa10/0x11e0 [ip_tables]
? ipt_do_table+0xa15/0x11e0 [ip_tables]
nft_do_chain_inet+0xdc/0x4a0 [nf_tables]
? __pfx_nft_do_chain_inet+0x10/0x10 [nf_tables]
? __pfx_ipt_do_table+0x10/0x10 [ip_tables]
nf_hook_slow+0xbe/0x210
? lock_is_held_type+0xb0/0x180
ip_local_deliver+0x2d0/0x4a0
? __pfx_ip_local_deliver+0x10/0x10
? __pfx_ip_local_deliver_finish+0x10/0x10
? ip_rcv_finish_core+0x75b/0x1470
? lock_is_held_type+0xb0/0x180
ip_list_rcv_finish+0x7f8/0xbb0
? ip_sublist_rcv+0x106/0x2f0
? __pfx_ip_list_rcv_finish+0x10/0x10
? __lock_release.isra.0+0x69/0x1a0
ip_sublist_rcv+0x8b/0x2f0
? __pfx_ip_sublist_rcv+0x10/0x10
? __pfx_ip_rcv_finish+0x10/0x10
? ip_rcv_core+0x619/0xd00
? kasan_save_stack+0x2f/0x50
ip_list_rcv+0x2dd/0x440
? asm_common_interrupt+0x26/0x40
? __pfx_ip_list_rcv+0x10/0x10
? drm_atomic_helper_commit_planes+0x3bd/0x1040 [drm_kms_helper]
? commit_tail+0x204/0x4b0 [drm_kms_helper]
? __lock_acquire+0x691/0xd00
__netif_receive_skb_list_core+0x6bf/0xa10
? __pfx___netif_receive_skb_list_core+0x10/0x10
? lock_acquire.part.0+0xc8/0x240
? netif_receive_skb_list_internal+0x382/0xc90
? lock_acquire+0x11a/0x140
netif_receive_skb_list_internal+0x603/0xc90
? dev_gro_receive+0x1e0/0x15f0
? __pfx_netif_receive_skb_list_internal+0x10/0x10
? napi_build_skb+0x55/0x1e0
? i40e_process_skb_fields+0x4a6/0xea0 [i40e]
? i40e_clean_rx_irq+0x96f/0x2140 [i40e]
napi_complete_done+0x1a4/0x900
? __pfx_napi_complete_done+0x10/0x10
i40e_napi_poll+0x408/0xb70 [i40e]
? __pfx_i40e_napi_poll+0x10/0x10 [i40e]
__napi_poll+0x351/0x520
net_rx_action+0x446/0xc30
? __pfx_net_rx_action+0x10/0x10
? do_raw_spin_unlock+0x59/0x230
? lock_release.part.0+0x1c/0x50
? sched_clock_cpu+0x69/0x630
? mark_held_locks+0x40/0x70
handle_softirqs+0x1de/0x830
? __pfx_handle_softirqs+0x10/0x10
? irqtime_account_irq+0x3e/0x2d0
__irq_exit_rcu+0x164/0x290
irq_exit_rcu+0xe/0x20
common_interrupt+0x85/0xa0
</IRQ>
<TASK>
asm_common_interrupt+0x26/0x40
RIP: 0010:memcpy_toio+0xa3/0x120
Code: 5c e9 d1 59 9f 01 48 85 db 74 ee 40 f6 c5 01 75 49 48 83 fb 01 76 06 40 f6 c5 02 75 29 48 89 d9 48 89 ef 4c 89 e6 48 c1 e9 02 <f3> a5 f6 c3 02 74 02 66 a5 f6 c3 01 74 01 a4 48 83 c4 18 5b 5d 41
RSP: 0018:ffff88811b3a7538 EFLAGS: 00010206
RAX: 0000000000000000 RBX: 0000000000001000 RCX: 00000000000003f0
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [syzbot] [bridge?] WARNING: locking bug in match_held_lock
2026-09-15 3:40 ` Shin'ichiro Kawasaki
@ 2026-09-15 4:06 ` Eric Dumazet
2026-09-15 6:04 ` [PATCH] rhashtable: Use separate lockdep keys for each lock Herbert Xu
0 siblings, 1 reply; 7+ messages in thread
From: Eric Dumazet @ 2026-09-15 4:06 UTC (permalink / raw)
To: Shin'ichiro Kawasaki
Cc: syzbot, bridge, davem, herbert, horms, idosch, kuba,
linux-kernel, netdev, pabeni, razor, steffen.klassert,
syzkaller-bugs, Thomas Graf, linux-crypto
On Mon, Sep 14, 2026 at 8:40 PM Shin'ichiro Kawasaki
<shinichiro.kawasaki@wdc.com> wrote:
>
> CC+: linux-crypto and rhashtable maintainers,
>
> On Sep 12, 2026 / 18:31, syzbot wrote:
> > Hello,
> >
> > syzbot found the following issue on:
> >
> > HEAD commit: a9d7ced84989 Add linux-next specific files for 20260908
> > git tree: linux-next
> > console output: https://syzkaller.appspot.com/x/log.txt?x=10880f49580000
> > kernel config: https://syzkaller.appspot.com/x/.config?x=17eeb09695a2b3c9
> > dashboard link: https://syzkaller.appspot.com/bug?extid=4d0e4d2db6dfde01b52f
> > compiler: Debian clang version 22.1.8 (++20260613092233+e80beda6e255-1~exp1~20260613092250.77), Debian LLD 22.1.8
> >
> > Unfortunately, I don't have any reproducer for this issue yet.
> >
> > Downloadable assets:
> > disk image: https://storage.googleapis.com/syzbot-assets/4f470407358e/disk-a9d7ced8.raw.xz
> > vmlinux: https://storage.googleapis.com/syzbot-assets/858b9d7ba687/vmlinux-a9d7ced8.xz
> > kernel image: https://storage.googleapis.com/syzbot-assets/ef971d22d75f/bzImage-a9d7ced8.xz
> >
> > IMPORTANT: if you fix the issue, please add the following tag to the commit:
> > Reported-by: syzbot+4d0e4d2db6dfde01b52f@syzkaller.appspotmail.com
> >
> > ------------[ cut here ]------------
> > Looking for class "&ht->mutex" with key xfrm_policy_init.__key.84, but found a different class "key" with the same key
> > WARNING: kernel/locking/lockdep.c:958 at look_up_lock_class+0x8c/0x110 kernel/locking/lockdep.c:955, CPU#1: kworker/1:6/5751
> > Modules linked in:
> > CPU: 1 UID: 0 PID: 5751 Comm: kworker/1:6 Tainted: G L syzkaller #0 PREEMPT(full)
> > Tainted: [L]=SOFTLOCKUP
> > Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 07/24/2026
> > Workqueue: usb_hub_wq hub_event
> > RIP: 0010:look_up_lock_class+0x9a/0x110 kernel/locking/lockdep.c:955
> > Code: 00 00 49 3b 46 18 0f 84 82 00 00 00 49 81 3e d0 44 58 94 74 79 48 8d 3d 44 f2 94 04 49 8b 16 49 8b 76 18 48 8b 8b b8 00 00 00 <67> 48 0f b9 3a eb 5d 90 89 f3 e8 67 0a f4 f8 e8 32 5c be f5 48 c7
> > RSP: 0018:ffffc90000a38070 EFLAGS: 00010002
> > RAX: ffffffff8c6bb940 RBX: ffffffff94478508 RCX: ffffffff8c6bb940
> > RDX: ffffffff9af23440 RSI: ffffffff8c6bb900 RDI: ffffffff907ddb20
> > RBP: 00000000ffffffff R08: 0000000000000100 R09: 0000000000000004
> > R10: 0000000000000003 R11: 0000000000000300 R12: 0000000000000246
> > R13: ffff8880307a8000 R14: ffffffff9af232c8 R15: ffffffff9af23440
> > FS: 0000000000000000(0000) GS:ffff888124db7000(0000) knlGS:0000000000000000
> > CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> > CR2: 0000001b3401aff8 CR3: 0000000074540000 CR4: 00000000003526f0
> > Call Trace:
> > <IRQ>
> > match_held_lock+0x9a/0x120 kernel/locking/lockdep.c:5364
> > __lock_is_held kernel/locking/lockdep.c:5654 [inline]
> > lock_is_held_type+0x89/0x150 kernel/locking/lockdep.c:6016
> > __rhashtable_lookup include/linux/rhashtable.h:623 [inline]
> > rhashtable_lookup include/linux/rhashtable.h:668 [inline]
> > xfrm_policy_inexact_lookup_rcu+0x60/0x750 net/xfrm/xfrm_policy.c:2068
> > xfrm_policy_lookup_bytype+0xb35/0x1840 net/xfrm/xfrm_policy.c:2193
> ...
>
> FYI, I also observed the WARN at look_up_lock_class() and match_held_lock()
> called in the rhashtable_lookup() context [1]. I used the kernel next-20260909.
> The WARN was observed during the run of blktests test case block/008 on dm-
> flakey device, but this test workload does not look related to the WARN. I tried
> to reproduce the WARN by repeating the test workload hundreds of times, and
> succeeded only once. The WARN looks rare, but I'm sure the WARN happned.
>
> The call trace that syzbot reported and that I observed look rather different.
> The common part across them is the rhashtable_lookup() call. So I think it is
> the better to involve rhashtable experts. I took the liberty CC to them.
>
>
> [1] WARN observed at blktests block/008 for dm-flakey
>
> WARNING: kernel/locking/lockdep.c:955 at look_up_lock_class+0xa8/0x170, CPU#14: kworker/14:1/309662
> Modules linked in: dm_flakey iscsi_target_mod tcm_loop target_core_pscsi target_core_file target_core_iblock xfs target_core_user target_core_mod nft_fib_inet nft_fib_ipv4 nft_fib_ipv6 nft_fib nft_reject_inet nf_reject_ipv4 nf_reject_ipv6 nft_reject qrtr nft_ct nft_chain_nat ip6table_nat ip6table_mangle ip6table_raw ip6table_security iptable_nat nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 iptable_mangle rfkill iptable_raw iptable_security nf_tables ip6table_filter ip6_tables iptable_filter ip_tables irdma ice sunrpc libie_fwlog gnss idpf libeth_xdp libie_pci libie_cp libeth ib_core intel_rapl_msr intel_rapl_common intel_uncore_frequency intel_uncore_frequency_common skx_edac skx_edac_common nfit libnvdimm x86_pkg_temp_thermal intel_powerclamp coretemp kvm_intel spi_nor mtd kvm i40e irqbypass iTCO_wdt rapl intel_pmc_bxt vfat ses intel_cstate libie fat intel_uncore libie_adminq enclosure i2c_i801 spi_intel_pci spi_intel i2c_smbus lpc_ich mei_me mei intel_pch_thermal wmi joydev ioatdma acpi_pad
> acpi_power_meter dca fuse dm_multipath zram lz4hc_compress zstd_compress ast drm_client_lib i2c_algo_bit drm_shmem_helper drm_kms_helper nvme drm nvme_core mpi3mr nvme_keyring nvme_auth scsi_transport_sas scsi_dh_alua pkcs8_key_parser scsi_dh_emc scsi_dh_rdac i2c_dev [last unloaded: null_blk]
> CPU: 14 UID: 0 PID: 309662 Comm: kworker/14:1 Tainted: G W 7.3.0-rc2-next-20260909-kts+ #1 PREEMPT(lazy)
> Tainted: [W]=WARN
> Hardware name: Supermicro Super Server/X11SPi-TF, BIOS 3.5 05/18/2021
> Workqueue: events drm_fb_helper_damage_work [drm_kms_helper]
> RIP: 0010:look_up_lock_class+0xa8/0x170
> Code: 39 6b 40 75 ed 48 8b 8b b8 00 00 00 49 8b 74 24 18 48 39 f1 74 34 49 8b 14 24 48 81 fa f0 31 7f 9a 74 27 48 8d 3d b8 66 4a 02 <67> 48 0f b9 3a 48 89 d8 48 8b 6c 24 10 4c 8b 64 24 18 48 8b 5c 24
> RSP: 0018:ffff888e40108088 EFLAGS: 00010002
> RAX: 0000000000000001 RBX: ffffffff9e852a78 RCX: ffffffff97838ae0
> RDX: ffffffffc271a2a0 RSI: ffffffff97838a60 RDI: ffffffff997aa470
> RBP: ffffffffc271a2a0 R08: 0000000000000001 R09: ffff888133ab3018
> R10: 0000000000000004 R11: ffff888e40108360 R12: ffff88812d59e1f8
> R13: 0000000000000003 R14: 0000000000000246 R15: 00000000ffffffff
> FS: 0000000000000000(0000) GS:ffff888ea59d3000(0000) knlGS:0000000000000000
> CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> CR2: 000055dba25b8c90 CR3: 00000002a6911004 CR4: 00000000007726f0
> PKRU: 55555554
> Call Trace:
> <IRQ>
> match_held_lock+0xdb/0x130
> lock_is_held_type+0xb0/0x180
> nft_rhash_lookup+0x541/0x7e0 [nf_tables]
> ? find_held_lock+0x2b/0x80
> ? __lock_release.isra.0+0x69/0x1a0
> ? lock_release.part.0+0x1c/0x50
> ? __pfx_nft_rhash_lookup+0x10/0x10 [nf_tables]
> nft_set_do_lookup+0x1ac/0x2a0 [nf_tables]
> ? fib_lookup_good_nhc+0x104/0x380
> nft_lookup_eval+0xcc/0x590 [nf_tables]
> ? lock_is_held_type+0xb0/0x180
> nft_do_chain+0x2a9/0x1680 [nf_tables]
> ? __lock_acquire+0x690/0xd00
> ? __pfx_nft_do_chain+0x10/0x10 [nf_tables]
> ? lock_acquire.part.0+0xc8/0x240
> ? find_held_lock+0x2b/0x80
> ? __local_bh_enable_ip+0xb4/0x150
> ? ipt_do_table+0xa10/0x11e0 [ip_tables]
> ? ipt_do_table+0xa15/0x11e0 [ip_tables]
> nft_do_chain_inet+0xdc/0x4a0 [nf_tables]
> ? __pfx_nft_do_chain_inet+0x10/0x10 [nf_tables]
> ? __pfx_ipt_do_table+0x10/0x10 [ip_tables]
> nf_hook_slow+0xbe/0x210
> ? lock_is_held_type+0xb0/0x180
> ip_local_deliver+0x2d0/0x4a0
> ? __pfx_ip_local_deliver+0x10/0x10
> ? __pfx_ip_local_deliver_finish+0x10/0x10
> ? ip_rcv_finish_core+0x75b/0x1470
> ? lock_is_held_type+0xb0/0x180
> ip_list_rcv_finish+0x7f8/0xbb0
> ? ip_sublist_rcv+0x106/0x2f0
> ? __pfx_ip_list_rcv_finish+0x10/0x10
> ? __lock_release.isra.0+0x69/0x1a0
> ip_sublist_rcv+0x8b/0x2f0
> ? __pfx_ip_sublist_rcv+0x10/0x10
> ? __pfx_ip_rcv_finish+0x10/0x10
> ? ip_rcv_core+0x619/0xd00
> ? kasan_save_stack+0x2f/0x50
> ip_list_rcv+0x2dd/0x440
> ? asm_common_interrupt+0x26/0x40
> ? __pfx_ip_list_rcv+0x10/0x10
> ? drm_atomic_helper_commit_planes+0x3bd/0x1040 [drm_kms_helper]
> ? commit_tail+0x204/0x4b0 [drm_kms_helper]
> ? __lock_acquire+0x691/0xd00
> __netif_receive_skb_list_core+0x6bf/0xa10
> ? __pfx___netif_receive_skb_list_core+0x10/0x10
> ? lock_acquire.part.0+0xc8/0x240
> ? netif_receive_skb_list_internal+0x382/0xc90
> ? lock_acquire+0x11a/0x140
> netif_receive_skb_list_internal+0x603/0xc90
> ? dev_gro_receive+0x1e0/0x15f0
> ? __pfx_netif_receive_skb_list_internal+0x10/0x10
> ? napi_build_skb+0x55/0x1e0
> ? i40e_process_skb_fields+0x4a6/0xea0 [i40e]
> ? i40e_clean_rx_irq+0x96f/0x2140 [i40e]
> napi_complete_done+0x1a4/0x900
> ? __pfx_napi_complete_done+0x10/0x10
> i40e_napi_poll+0x408/0xb70 [i40e]
> ? __pfx_i40e_napi_poll+0x10/0x10 [i40e]
> __napi_poll+0x351/0x520
> net_rx_action+0x446/0xc30
> ? __pfx_net_rx_action+0x10/0x10
> ? do_raw_spin_unlock+0x59/0x230
> ? lock_release.part.0+0x1c/0x50
> ? sched_clock_cpu+0x69/0x630
> ? mark_held_locks+0x40/0x70
> handle_softirqs+0x1de/0x830
> ? __pfx_handle_softirqs+0x10/0x10
> ? irqtime_account_irq+0x3e/0x2d0
> __irq_exit_rcu+0x164/0x290
> irq_exit_rcu+0xe/0x20
> common_interrupt+0x85/0xa0
> </IRQ>
> <TASK>
> asm_common_interrupt+0x26/0x40
> RIP: 0010:memcpy_toio+0xa3/0x120
> Code: 5c e9 d1 59 9f 01 48 85 db 74 ee 40 f6 c5 01 75 49 48 83 fb 01 76 06 40 f6 c5 02 75 29 48 89 d9 48 89 ef 4c 89 e6 48 c1 e9 02 <f3> a5 f6 c3 02 74 02 66 a5 f6 c3 01 74 01 a4 48 83 c4 18 5b 5d 41
> RSP: 0018:ffff88811b3a7538 EFLAGS: 00010206
> RAX: 0000000000000000 RBX: 0000000000001000 RCX: 00000000000003f0
Try to revert 4333ab90aaae ("rhashtable: use private lockdep class for
all locks.")
Thanks.
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH] rhashtable: Use separate lockdep keys for each lock
2026-09-15 4:06 ` Eric Dumazet
@ 2026-09-15 6:04 ` Herbert Xu
2026-09-15 21:06 ` NeilBrown
2026-09-16 8:00 ` [v2 PATCH] " Herbert Xu
0 siblings, 2 replies; 7+ messages in thread
From: Herbert Xu @ 2026-09-15 6:04 UTC (permalink / raw)
To: Eric Dumazet
Cc: Shin'ichiro Kawasaki, syzbot, bridge, davem, horms, idosch,
kuba, linux-kernel, netdev, pabeni, razor, steffen.klassert,
syzkaller-bugs, Thomas Graf, linux-crypto, NeilBrown, quanyeyang
On Mon, Sep 14, 2026 at 09:06:49PM -0700, Eric Dumazet wrote:
>
> Try to revert 4333ab90aaae ("rhashtable: use private lockdep class for
> all locks.")
Yes this is indeed buggy. I know nothing about lockdep but Gemini
reckons that it should use separate keys instead of different
depths which seems fair enough:
---8<---
Use separate lockdep keys for the different types of locks in
rhashtable (mutex, spin lock, and bucket locks). They are
separate and not normally nested with respect to each other.
Also move the rhashtable_init/rhltable_init kdoc to the header
file as that's where the macros are defined.
Fixes: 4333ab90aaae ("rhashtable: use private lockdep class for all locks.")
Reported-by: syzbot+4d0e4d2db6dfde01b52f@syzkaller.appspotmail.com
Assisted-by: Gemini:gemini-3.6-flash
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
diff --git a/include/linux/rhashtable-types.h b/include/linux/rhashtable-types.h
index 0e1b172a4f6c..afbc12ba71f5 100644
--- a/include/linux/rhashtable-types.h
+++ b/include/linux/rhashtable-types.h
@@ -70,6 +70,14 @@ struct rhashtable_params {
rht_obj_cmpfn_t obj_cmpfn;
};
+struct rhashtable_lockdep_keys {
+#ifdef CONFIG_LOCKDEP
+ struct lock_class_key lock_key;
+ struct lock_class_key mutex_key;
+ struct lock_class_key bucket_key;
+#endif
+};
+
/**
* struct rhashtable - Hash table handle
* @tbl: Bucket table
@@ -141,24 +149,77 @@ struct rhashtable_iter {
int __rhashtable_init_noprof(struct rhashtable *ht,
const struct rhashtable_params *params,
- struct lock_class_key *key);
+ struct rhashtable_lockdep_keys *keys);
#define rhashtable_init_noprof(ht, params) \
({ \
- static struct lock_class_key __key; \
+ static struct rhashtable_lockdep_keys __keys; \
\
- __rhashtable_init_noprof(ht, params, &__key); \
+ __rhashtable_init_noprof(ht, params, &__keys); \
})
+
+/**
+ * rhashtable_init - initialize a new hash table
+ * @ht: hash table to be initialized
+ * @params: configuration parameters
+ *
+ * Initializes a new hash table based on the provided configuration
+ * parameters. A table can be configured either with a variable or
+ * fixed length key:
+ *
+ * Configuration Example 1: Fixed length keys
+ * struct test_obj {
+ * int key;
+ * void * my_member;
+ * struct rhash_head node;
+ * };
+ *
+ * struct rhashtable_params params = {
+ * .head_offset = offsetof(struct test_obj, node),
+ * .key_offset = offsetof(struct test_obj, key),
+ * .key_len = sizeof(int),
+ * .hashfn = jhash,
+ * };
+ *
+ * Configuration Example 2: Variable length keys
+ * struct test_obj {
+ * [...]
+ * struct rhash_head node;
+ * };
+ *
+ * u32 my_hash_fn(const void *data, u32 len, u32 seed)
+ * {
+ * struct test_obj *obj = data;
+ *
+ * return [... hash ...];
+ * }
+ *
+ * struct rhashtable_params params = {
+ * .head_offset = offsetof(struct test_obj, node),
+ * .hashfn = jhash,
+ * .obj_hashfn = my_hash_fn,
+ * };
+ */
#define rhashtable_init(...) alloc_hooks(rhashtable_init_noprof(__VA_ARGS__))
int __rhltable_init_noprof(struct rhltable *hlt,
const struct rhashtable_params *params,
- struct lock_class_key *key);
+ struct rhashtable_lockdep_keys *keys);
#define rhltable_init_noprof(hlt, params) \
({ \
- static struct lock_class_key __key; \
+ static struct rhashtable_lockdep_keys __keys; \
\
- __rhltable_init_noprof(hlt, params, &__key); \
+ __rhltable_init_noprof(hlt, params, &__keys); \
})
+
+/**
+ * rhltable_init - initialize a new hash list table
+ * @hlt: hash list table to be initialized
+ * @params: configuration parameters
+ *
+ * Initializes a new hash list table.
+ *
+ * See documentation for rhashtable_init.
+ */
#define rhltable_init(...) alloc_hooks(rhltable_init_noprof(__VA_ARGS__))
#endif /* _LINUX_RHASHTABLE_TYPES_H */
diff --git a/include/linux/rhashtable.h b/include/linux/rhashtable.h
index 6c5e6d9accba..ec853c1b9af3 100644
--- a/include/linux/rhashtable.h
+++ b/include/linux/rhashtable.h
@@ -328,8 +328,7 @@ static inline unsigned long rht_lock_nested(struct bucket_table *tbl,
local_irq_save(flags);
bit_spin_lock(0, (unsigned long *)bucket);
- /* subclass 0 is used for ->lock and 1 for ->mutex. 2+ for bitlocks */
- lock_acquire_exclusive(&tbl->dep_map, subclass+2, 0, NULL, _THIS_IP_);
+ lock_acquire_exclusive(&tbl->dep_map, subclass, 0, NULL, _THIS_IP_);
return flags;
}
diff --git a/lib/rhashtable.c b/lib/rhashtable.c
index 5da0e53a8d42..918f15a2ac69 100644
--- a/lib/rhashtable.c
+++ b/lib/rhashtable.c
@@ -432,7 +432,7 @@ static void rht_deferred_worker(struct work_struct *work)
int err = 0;
ht = container_of(work, struct rhashtable, run_work);
- mutex_lock_nested(&ht->mutex, 1);
+ mutex_lock(&ht->mutex);
tbl = rht_dereference(ht->tbl, ht);
tbl = rhashtable_last_table(ht, tbl);
@@ -1122,51 +1122,9 @@ static u32 rhashtable_jhash2(const void *key, u32 length, u32 seed)
return jhash2(key, length, seed);
}
-/**
- * rhashtable_init - initialize a new hash table
- * @ht: hash table to be initialized
- * @params: configuration parameters
- *
- * Initializes a new hash table based on the provided configuration
- * parameters. A table can be configured either with a variable or
- * fixed length key:
- *
- * Configuration Example 1: Fixed length keys
- * struct test_obj {
- * int key;
- * void * my_member;
- * struct rhash_head node;
- * };
- *
- * struct rhashtable_params params = {
- * .head_offset = offsetof(struct test_obj, node),
- * .key_offset = offsetof(struct test_obj, key),
- * .key_len = sizeof(int),
- * .hashfn = jhash,
- * };
- *
- * Configuration Example 2: Variable length keys
- * struct test_obj {
- * [...]
- * struct rhash_head node;
- * };
- *
- * u32 my_hash_fn(const void *data, u32 len, u32 seed)
- * {
- * struct test_obj *obj = data;
- *
- * return [... hash ...];
- * }
- *
- * struct rhashtable_params params = {
- * .head_offset = offsetof(struct test_obj, node),
- * .hashfn = jhash,
- * .obj_hashfn = my_hash_fn,
- * };
- */
int __rhashtable_init_noprof(struct rhashtable *ht,
- const struct rhashtable_params *params,
- struct lock_class_key *key)
+ const struct rhashtable_params *params,
+ struct rhashtable_lockdep_keys *keys)
{
struct bucket_table *tbl;
size_t size;
@@ -1176,13 +1134,11 @@ int __rhashtable_init_noprof(struct rhashtable *ht,
return -EINVAL;
memset(ht, 0, sizeof(*ht));
- /* mutex_lock must use nesting level 1 */
- mutex_init_with_key(&ht->mutex, key);
+ mutex_init_with_key(&ht->mutex, &keys->mutex_key);
spin_lock_init(&ht->lock);
- /* spin_lock can use nesting level 0 */
- lockdep_set_class(&ht->lock, key);
+ lockdep_set_class(&ht->lock, &keys->lock_key);
#ifdef CONFIG_LOCKDEP
- ht->lockdep_key = key;
+ ht->lockdep_key = &keys->bucket_key;
#endif
memcpy(&ht->p, params, sizeof(*params));
@@ -1236,22 +1192,13 @@ int __rhashtable_init_noprof(struct rhashtable *ht,
}
EXPORT_SYMBOL_GPL(__rhashtable_init_noprof);
-/**
- * rhltable_init - initialize a new hash list table
- * @hlt: hash list table to be initialized
- * @params: configuration parameters
- *
- * Initializes a new hash list table.
- *
- * See documentation for rhashtable_init.
- */
int __rhltable_init_noprof(struct rhltable *hlt,
const struct rhashtable_params *params,
- struct lock_class_key *key)
+ struct rhashtable_lockdep_keys *keys)
{
int err;
- err = __rhashtable_init_noprof(&hlt->ht, params, key);
+ err = __rhashtable_init_noprof(&hlt->ht, params, keys);
hlt->ht.rhlist = true;
return err;
}
diff --git a/lib/test_rhashtable.c b/lib/test_rhashtable.c
index 85a615e74591..b767a38a74f9 100644
--- a/lib/test_rhashtable.c
+++ b/lib/test_rhashtable.c
@@ -477,7 +477,7 @@ static unsigned int __init print_ht(struct rhltable *rhlt)
ht = &rhlt->ht;
/* Take the mutex to avoid RCU warning */
- mutex_lock_nested(&ht->mutex, 1);
+ mutex_lock(&ht->mutex);
tbl = rht_dereference(ht->tbl, ht);
for (i = 0; i < tbl->size; i++) {
struct rhash_head *pos, *next;
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] rhashtable: Use separate lockdep keys for each lock
2026-09-15 6:04 ` [PATCH] rhashtable: Use separate lockdep keys for each lock Herbert Xu
@ 2026-09-15 21:06 ` NeilBrown
2026-09-16 8:00 ` [v2 PATCH] " Herbert Xu
1 sibling, 0 replies; 7+ messages in thread
From: NeilBrown @ 2026-09-15 21:06 UTC (permalink / raw)
To: Herbert Xu
Cc: Eric Dumazet, Shin'ichiro Kawasaki, syzbot, bridge, davem,
horms, idosch, kuba, linux-kernel, netdev, pabeni, razor,
steffen.klassert, syzkaller-bugs, Thomas Graf, linux-crypto,
quanyeyang
On Tue, 15 Sep 2026, Herbert Xu wrote:
> On Mon, Sep 14, 2026 at 09:06:49PM -0700, Eric Dumazet wrote:
> >
> > Try to revert 4333ab90aaae ("rhashtable: use private lockdep class for
> > all locks.")
>
> Yes this is indeed buggy. I know nothing about lockdep but Gemini
> reckons that it should use separate keys instead of different
> depths which seems fair enough:
>
> ---8<---
> Use separate lockdep keys for the different types of locks in
> rhashtable (mutex, spin lock, and bucket locks). They are
> separate and not normally nested with respect to each other.
>
> Also move the rhashtable_init/rhltable_init kdoc to the header
> file as that's where the macros are defined.
>
> Fixes: 4333ab90aaae ("rhashtable: use private lockdep class for all locks.")
> Reported-by: syzbot+4d0e4d2db6dfde01b52f@syzkaller.appspotmail.com
> Assisted-by: Gemini:gemini-3.6-flash
> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
That's a much better approach - thanks for that.
Reviewed-by: NeilBrown <neil@brown.name>
Thanks,
NeilBrown
>
> diff --git a/include/linux/rhashtable-types.h b/include/linux/rhashtable-types.h
> index 0e1b172a4f6c..afbc12ba71f5 100644
> --- a/include/linux/rhashtable-types.h
> +++ b/include/linux/rhashtable-types.h
> @@ -70,6 +70,14 @@ struct rhashtable_params {
> rht_obj_cmpfn_t obj_cmpfn;
> };
>
> +struct rhashtable_lockdep_keys {
> +#ifdef CONFIG_LOCKDEP
> + struct lock_class_key lock_key;
> + struct lock_class_key mutex_key;
> + struct lock_class_key bucket_key;
> +#endif
> +};
> +
> /**
> * struct rhashtable - Hash table handle
> * @tbl: Bucket table
> @@ -141,24 +149,77 @@ struct rhashtable_iter {
>
> int __rhashtable_init_noprof(struct rhashtable *ht,
> const struct rhashtable_params *params,
> - struct lock_class_key *key);
> + struct rhashtable_lockdep_keys *keys);
> #define rhashtable_init_noprof(ht, params) \
> ({ \
> - static struct lock_class_key __key; \
> + static struct rhashtable_lockdep_keys __keys; \
> \
> - __rhashtable_init_noprof(ht, params, &__key); \
> + __rhashtable_init_noprof(ht, params, &__keys); \
> })
> +
> +/**
> + * rhashtable_init - initialize a new hash table
> + * @ht: hash table to be initialized
> + * @params: configuration parameters
> + *
> + * Initializes a new hash table based on the provided configuration
> + * parameters. A table can be configured either with a variable or
> + * fixed length key:
> + *
> + * Configuration Example 1: Fixed length keys
> + * struct test_obj {
> + * int key;
> + * void * my_member;
> + * struct rhash_head node;
> + * };
> + *
> + * struct rhashtable_params params = {
> + * .head_offset = offsetof(struct test_obj, node),
> + * .key_offset = offsetof(struct test_obj, key),
> + * .key_len = sizeof(int),
> + * .hashfn = jhash,
> + * };
> + *
> + * Configuration Example 2: Variable length keys
> + * struct test_obj {
> + * [...]
> + * struct rhash_head node;
> + * };
> + *
> + * u32 my_hash_fn(const void *data, u32 len, u32 seed)
> + * {
> + * struct test_obj *obj = data;
> + *
> + * return [... hash ...];
> + * }
> + *
> + * struct rhashtable_params params = {
> + * .head_offset = offsetof(struct test_obj, node),
> + * .hashfn = jhash,
> + * .obj_hashfn = my_hash_fn,
> + * };
> + */
> #define rhashtable_init(...) alloc_hooks(rhashtable_init_noprof(__VA_ARGS__))
>
> int __rhltable_init_noprof(struct rhltable *hlt,
> const struct rhashtable_params *params,
> - struct lock_class_key *key);
> + struct rhashtable_lockdep_keys *keys);
> #define rhltable_init_noprof(hlt, params) \
> ({ \
> - static struct lock_class_key __key; \
> + static struct rhashtable_lockdep_keys __keys; \
> \
> - __rhltable_init_noprof(hlt, params, &__key); \
> + __rhltable_init_noprof(hlt, params, &__keys); \
> })
> +
> +/**
> + * rhltable_init - initialize a new hash list table
> + * @hlt: hash list table to be initialized
> + * @params: configuration parameters
> + *
> + * Initializes a new hash list table.
> + *
> + * See documentation for rhashtable_init.
> + */
> #define rhltable_init(...) alloc_hooks(rhltable_init_noprof(__VA_ARGS__))
>
> #endif /* _LINUX_RHASHTABLE_TYPES_H */
> diff --git a/include/linux/rhashtable.h b/include/linux/rhashtable.h
> index 6c5e6d9accba..ec853c1b9af3 100644
> --- a/include/linux/rhashtable.h
> +++ b/include/linux/rhashtable.h
> @@ -328,8 +328,7 @@ static inline unsigned long rht_lock_nested(struct bucket_table *tbl,
>
> local_irq_save(flags);
> bit_spin_lock(0, (unsigned long *)bucket);
> - /* subclass 0 is used for ->lock and 1 for ->mutex. 2+ for bitlocks */
> - lock_acquire_exclusive(&tbl->dep_map, subclass+2, 0, NULL, _THIS_IP_);
> + lock_acquire_exclusive(&tbl->dep_map, subclass, 0, NULL, _THIS_IP_);
> return flags;
> }
>
> diff --git a/lib/rhashtable.c b/lib/rhashtable.c
> index 5da0e53a8d42..918f15a2ac69 100644
> --- a/lib/rhashtable.c
> +++ b/lib/rhashtable.c
> @@ -432,7 +432,7 @@ static void rht_deferred_worker(struct work_struct *work)
> int err = 0;
>
> ht = container_of(work, struct rhashtable, run_work);
> - mutex_lock_nested(&ht->mutex, 1);
> + mutex_lock(&ht->mutex);
>
> tbl = rht_dereference(ht->tbl, ht);
> tbl = rhashtable_last_table(ht, tbl);
> @@ -1122,51 +1122,9 @@ static u32 rhashtable_jhash2(const void *key, u32 length, u32 seed)
> return jhash2(key, length, seed);
> }
>
> -/**
> - * rhashtable_init - initialize a new hash table
> - * @ht: hash table to be initialized
> - * @params: configuration parameters
> - *
> - * Initializes a new hash table based on the provided configuration
> - * parameters. A table can be configured either with a variable or
> - * fixed length key:
> - *
> - * Configuration Example 1: Fixed length keys
> - * struct test_obj {
> - * int key;
> - * void * my_member;
> - * struct rhash_head node;
> - * };
> - *
> - * struct rhashtable_params params = {
> - * .head_offset = offsetof(struct test_obj, node),
> - * .key_offset = offsetof(struct test_obj, key),
> - * .key_len = sizeof(int),
> - * .hashfn = jhash,
> - * };
> - *
> - * Configuration Example 2: Variable length keys
> - * struct test_obj {
> - * [...]
> - * struct rhash_head node;
> - * };
> - *
> - * u32 my_hash_fn(const void *data, u32 len, u32 seed)
> - * {
> - * struct test_obj *obj = data;
> - *
> - * return [... hash ...];
> - * }
> - *
> - * struct rhashtable_params params = {
> - * .head_offset = offsetof(struct test_obj, node),
> - * .hashfn = jhash,
> - * .obj_hashfn = my_hash_fn,
> - * };
> - */
> int __rhashtable_init_noprof(struct rhashtable *ht,
> - const struct rhashtable_params *params,
> - struct lock_class_key *key)
> + const struct rhashtable_params *params,
> + struct rhashtable_lockdep_keys *keys)
> {
> struct bucket_table *tbl;
> size_t size;
> @@ -1176,13 +1134,11 @@ int __rhashtable_init_noprof(struct rhashtable *ht,
> return -EINVAL;
>
> memset(ht, 0, sizeof(*ht));
> - /* mutex_lock must use nesting level 1 */
> - mutex_init_with_key(&ht->mutex, key);
> + mutex_init_with_key(&ht->mutex, &keys->mutex_key);
> spin_lock_init(&ht->lock);
> - /* spin_lock can use nesting level 0 */
> - lockdep_set_class(&ht->lock, key);
> + lockdep_set_class(&ht->lock, &keys->lock_key);
> #ifdef CONFIG_LOCKDEP
> - ht->lockdep_key = key;
> + ht->lockdep_key = &keys->bucket_key;
> #endif
> memcpy(&ht->p, params, sizeof(*params));
>
> @@ -1236,22 +1192,13 @@ int __rhashtable_init_noprof(struct rhashtable *ht,
> }
> EXPORT_SYMBOL_GPL(__rhashtable_init_noprof);
>
> -/**
> - * rhltable_init - initialize a new hash list table
> - * @hlt: hash list table to be initialized
> - * @params: configuration parameters
> - *
> - * Initializes a new hash list table.
> - *
> - * See documentation for rhashtable_init.
> - */
> int __rhltable_init_noprof(struct rhltable *hlt,
> const struct rhashtable_params *params,
> - struct lock_class_key *key)
> + struct rhashtable_lockdep_keys *keys)
> {
> int err;
>
> - err = __rhashtable_init_noprof(&hlt->ht, params, key);
> + err = __rhashtable_init_noprof(&hlt->ht, params, keys);
> hlt->ht.rhlist = true;
> return err;
> }
> diff --git a/lib/test_rhashtable.c b/lib/test_rhashtable.c
> index 85a615e74591..b767a38a74f9 100644
> --- a/lib/test_rhashtable.c
> +++ b/lib/test_rhashtable.c
> @@ -477,7 +477,7 @@ static unsigned int __init print_ht(struct rhltable *rhlt)
>
> ht = &rhlt->ht;
> /* Take the mutex to avoid RCU warning */
> - mutex_lock_nested(&ht->mutex, 1);
> + mutex_lock(&ht->mutex);
> tbl = rht_dereference(ht->tbl, ht);
> for (i = 0; i < tbl->size; i++) {
> struct rhash_head *pos, *next;
> --
> Email: Herbert Xu <herbert@gondor.apana.org.au>
> Home Page: http://gondor.apana.org.au/~herbert/
> PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
>
^ permalink raw reply [flat|nested] 7+ messages in thread
* [v2 PATCH] rhashtable: Use separate lockdep keys for each lock
2026-09-15 6:04 ` [PATCH] rhashtable: Use separate lockdep keys for each lock Herbert Xu
2026-09-15 21:06 ` NeilBrown
@ 2026-09-16 8:00 ` Herbert Xu
2026-09-16 8:46 ` [v3 " Herbert Xu
1 sibling, 1 reply; 7+ messages in thread
From: Herbert Xu @ 2026-09-16 8:00 UTC (permalink / raw)
To: Eric Dumazet
Cc: Shin'ichiro Kawasaki, syzbot, davem, horms, idosch, kuba,
linux-kernel, pabeni, razor, steffen.klassert, syzkaller-bugs,
Thomas Graf, linux-crypto, NeilBrown, quanyeyang
v2 fixes the build failure when LOCKDEP is disabled.
---8<---
Use separate lockdep keys for the different types of locks in
rhashtable (mutex, spin lock, and bucket locks). They are
separate and not normally nested with respect to each other.
Also move the rhashtable_init/rhltable_init kdoc to the header
file as that's where the macros are defined.
Fixes: 4333ab90aaae ("rhashtable: use private lockdep class for all locks.")
Reported-by: syzbot+4d0e4d2db6dfde01b52f@syzkaller.appspotmail.com
Assisted-by: Gemini:gemini-3.6-flash
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Reviewed-by: NeilBrown <neil@brown.name>
diff --git a/include/linux/rhashtable-types.h b/include/linux/rhashtable-types.h
index 0e1b172a4f6c..3576b8f08aff 100644
--- a/include/linux/rhashtable-types.h
+++ b/include/linux/rhashtable-types.h
@@ -70,6 +70,12 @@ struct rhashtable_params {
rht_obj_cmpfn_t obj_cmpfn;
};
+struct rhashtable_lockdep_keys {
+ struct lock_class_key lock_key;
+ struct lock_class_key mutex_key;
+ struct lock_class_key bucket_key;
+};
+
/**
* struct rhashtable - Hash table handle
* @tbl: Bucket table
@@ -141,24 +147,77 @@ struct rhashtable_iter {
int __rhashtable_init_noprof(struct rhashtable *ht,
const struct rhashtable_params *params,
- struct lock_class_key *key);
+ struct rhashtable_lockdep_keys *keys);
#define rhashtable_init_noprof(ht, params) \
({ \
- static struct lock_class_key __key; \
+ static struct rhashtable_lockdep_keys __keys; \
\
- __rhashtable_init_noprof(ht, params, &__key); \
+ __rhashtable_init_noprof(ht, params, &__keys); \
})
+
+/**
+ * rhashtable_init - initialize a new hash table
+ * @ht: hash table to be initialized
+ * @params: configuration parameters
+ *
+ * Initializes a new hash table based on the provided configuration
+ * parameters. A table can be configured either with a variable or
+ * fixed length key:
+ *
+ * Configuration Example 1: Fixed length keys
+ * struct test_obj {
+ * int key;
+ * void * my_member;
+ * struct rhash_head node;
+ * };
+ *
+ * struct rhashtable_params params = {
+ * .head_offset = offsetof(struct test_obj, node),
+ * .key_offset = offsetof(struct test_obj, key),
+ * .key_len = sizeof(int),
+ * .hashfn = jhash,
+ * };
+ *
+ * Configuration Example 2: Variable length keys
+ * struct test_obj {
+ * [...]
+ * struct rhash_head node;
+ * };
+ *
+ * u32 my_hash_fn(const void *data, u32 len, u32 seed)
+ * {
+ * struct test_obj *obj = data;
+ *
+ * return [... hash ...];
+ * }
+ *
+ * struct rhashtable_params params = {
+ * .head_offset = offsetof(struct test_obj, node),
+ * .hashfn = jhash,
+ * .obj_hashfn = my_hash_fn,
+ * };
+ */
#define rhashtable_init(...) alloc_hooks(rhashtable_init_noprof(__VA_ARGS__))
int __rhltable_init_noprof(struct rhltable *hlt,
const struct rhashtable_params *params,
- struct lock_class_key *key);
+ struct rhashtable_lockdep_keys *keys);
#define rhltable_init_noprof(hlt, params) \
({ \
- static struct lock_class_key __key; \
+ static struct rhashtable_lockdep_keys __keys; \
\
- __rhltable_init_noprof(hlt, params, &__key); \
+ __rhltable_init_noprof(hlt, params, &__keys); \
})
+
+/**
+ * rhltable_init - initialize a new hash list table
+ * @hlt: hash list table to be initialized
+ * @params: configuration parameters
+ *
+ * Initializes a new hash list table.
+ *
+ * See documentation for rhashtable_init.
+ */
#define rhltable_init(...) alloc_hooks(rhltable_init_noprof(__VA_ARGS__))
#endif /* _LINUX_RHASHTABLE_TYPES_H */
diff --git a/include/linux/rhashtable.h b/include/linux/rhashtable.h
index 6c5e6d9accba..ec853c1b9af3 100644
--- a/include/linux/rhashtable.h
+++ b/include/linux/rhashtable.h
@@ -328,8 +328,7 @@ static inline unsigned long rht_lock_nested(struct bucket_table *tbl,
local_irq_save(flags);
bit_spin_lock(0, (unsigned long *)bucket);
- /* subclass 0 is used for ->lock and 1 for ->mutex. 2+ for bitlocks */
- lock_acquire_exclusive(&tbl->dep_map, subclass+2, 0, NULL, _THIS_IP_);
+ lock_acquire_exclusive(&tbl->dep_map, subclass, 0, NULL, _THIS_IP_);
return flags;
}
diff --git a/lib/rhashtable.c b/lib/rhashtable.c
index 5da0e53a8d42..918f15a2ac69 100644
--- a/lib/rhashtable.c
+++ b/lib/rhashtable.c
@@ -432,7 +432,7 @@ static void rht_deferred_worker(struct work_struct *work)
int err = 0;
ht = container_of(work, struct rhashtable, run_work);
- mutex_lock_nested(&ht->mutex, 1);
+ mutex_lock(&ht->mutex);
tbl = rht_dereference(ht->tbl, ht);
tbl = rhashtable_last_table(ht, tbl);
@@ -1122,51 +1122,9 @@ static u32 rhashtable_jhash2(const void *key, u32 length, u32 seed)
return jhash2(key, length, seed);
}
-/**
- * rhashtable_init - initialize a new hash table
- * @ht: hash table to be initialized
- * @params: configuration parameters
- *
- * Initializes a new hash table based on the provided configuration
- * parameters. A table can be configured either with a variable or
- * fixed length key:
- *
- * Configuration Example 1: Fixed length keys
- * struct test_obj {
- * int key;
- * void * my_member;
- * struct rhash_head node;
- * };
- *
- * struct rhashtable_params params = {
- * .head_offset = offsetof(struct test_obj, node),
- * .key_offset = offsetof(struct test_obj, key),
- * .key_len = sizeof(int),
- * .hashfn = jhash,
- * };
- *
- * Configuration Example 2: Variable length keys
- * struct test_obj {
- * [...]
- * struct rhash_head node;
- * };
- *
- * u32 my_hash_fn(const void *data, u32 len, u32 seed)
- * {
- * struct test_obj *obj = data;
- *
- * return [... hash ...];
- * }
- *
- * struct rhashtable_params params = {
- * .head_offset = offsetof(struct test_obj, node),
- * .hashfn = jhash,
- * .obj_hashfn = my_hash_fn,
- * };
- */
int __rhashtable_init_noprof(struct rhashtable *ht,
- const struct rhashtable_params *params,
- struct lock_class_key *key)
+ const struct rhashtable_params *params,
+ struct rhashtable_lockdep_keys *keys)
{
struct bucket_table *tbl;
size_t size;
@@ -1176,13 +1134,11 @@ int __rhashtable_init_noprof(struct rhashtable *ht,
return -EINVAL;
memset(ht, 0, sizeof(*ht));
- /* mutex_lock must use nesting level 1 */
- mutex_init_with_key(&ht->mutex, key);
+ mutex_init_with_key(&ht->mutex, &keys->mutex_key);
spin_lock_init(&ht->lock);
- /* spin_lock can use nesting level 0 */
- lockdep_set_class(&ht->lock, key);
+ lockdep_set_class(&ht->lock, &keys->lock_key);
#ifdef CONFIG_LOCKDEP
- ht->lockdep_key = key;
+ ht->lockdep_key = &keys->bucket_key;
#endif
memcpy(&ht->p, params, sizeof(*params));
@@ -1236,22 +1192,13 @@ int __rhashtable_init_noprof(struct rhashtable *ht,
}
EXPORT_SYMBOL_GPL(__rhashtable_init_noprof);
-/**
- * rhltable_init - initialize a new hash list table
- * @hlt: hash list table to be initialized
- * @params: configuration parameters
- *
- * Initializes a new hash list table.
- *
- * See documentation for rhashtable_init.
- */
int __rhltable_init_noprof(struct rhltable *hlt,
const struct rhashtable_params *params,
- struct lock_class_key *key)
+ struct rhashtable_lockdep_keys *keys)
{
int err;
- err = __rhashtable_init_noprof(&hlt->ht, params, key);
+ err = __rhashtable_init_noprof(&hlt->ht, params, keys);
hlt->ht.rhlist = true;
return err;
}
diff --git a/lib/test_rhashtable.c b/lib/test_rhashtable.c
index 85a615e74591..b767a38a74f9 100644
--- a/lib/test_rhashtable.c
+++ b/lib/test_rhashtable.c
@@ -477,7 +477,7 @@ static unsigned int __init print_ht(struct rhltable *rhlt)
ht = &rhlt->ht;
/* Take the mutex to avoid RCU warning */
- mutex_lock_nested(&ht->mutex, 1);
+ mutex_lock(&ht->mutex);
tbl = rht_dereference(ht->tbl, ht);
for (i = 0; i < tbl->size; i++) {
struct rhash_head *pos, *next;
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply [flat|nested] 7+ messages in thread
* [v3 PATCH] rhashtable: Use separate lockdep keys for each lock
2026-09-16 8:00 ` [v2 PATCH] " Herbert Xu
@ 2026-09-16 8:46 ` Herbert Xu
0 siblings, 0 replies; 7+ messages in thread
From: Herbert Xu @ 2026-09-16 8:46 UTC (permalink / raw)
To: Eric Dumazet
Cc: Shin'ichiro Kawasaki, syzbot, davem, horms, idosch, kuba,
linux-kernel, pabeni, razor, steffen.klassert, syzkaller-bugs,
Thomas Graf, linux-crypto, NeilBrown, quanyeyang
v3 removes an obsolete comment regarding the use of nesting level 2 or more.
---8<---
Use separate lockdep keys for the different types of locks in
rhashtable (mutex, spin lock, and bucket locks). They are
separate and not normally nested with respect to each other.
Also move the rhashtable_init/rhltable_init kdoc to the header
file as that's where the macros are defined.
Fixes: 4333ab90aaae ("rhashtable: use private lockdep class for all locks.")
Reported-by: syzbot+4d0e4d2db6dfde01b52f@syzkaller.appspotmail.com
Assisted-by: Gemini:gemini-3.6-flash
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Reviewed-by: NeilBrown <neil@brown.name>
diff --git a/include/linux/rhashtable-types.h b/include/linux/rhashtable-types.h
index 0e1b172a4f6c..3576b8f08aff 100644
--- a/include/linux/rhashtable-types.h
+++ b/include/linux/rhashtable-types.h
@@ -70,6 +70,12 @@ struct rhashtable_params {
rht_obj_cmpfn_t obj_cmpfn;
};
+struct rhashtable_lockdep_keys {
+ struct lock_class_key lock_key;
+ struct lock_class_key mutex_key;
+ struct lock_class_key bucket_key;
+};
+
/**
* struct rhashtable - Hash table handle
* @tbl: Bucket table
@@ -141,24 +147,77 @@ struct rhashtable_iter {
int __rhashtable_init_noprof(struct rhashtable *ht,
const struct rhashtable_params *params,
- struct lock_class_key *key);
+ struct rhashtable_lockdep_keys *keys);
#define rhashtable_init_noprof(ht, params) \
({ \
- static struct lock_class_key __key; \
+ static struct rhashtable_lockdep_keys __keys; \
\
- __rhashtable_init_noprof(ht, params, &__key); \
+ __rhashtable_init_noprof(ht, params, &__keys); \
})
+
+/**
+ * rhashtable_init - initialize a new hash table
+ * @ht: hash table to be initialized
+ * @params: configuration parameters
+ *
+ * Initializes a new hash table based on the provided configuration
+ * parameters. A table can be configured either with a variable or
+ * fixed length key:
+ *
+ * Configuration Example 1: Fixed length keys
+ * struct test_obj {
+ * int key;
+ * void * my_member;
+ * struct rhash_head node;
+ * };
+ *
+ * struct rhashtable_params params = {
+ * .head_offset = offsetof(struct test_obj, node),
+ * .key_offset = offsetof(struct test_obj, key),
+ * .key_len = sizeof(int),
+ * .hashfn = jhash,
+ * };
+ *
+ * Configuration Example 2: Variable length keys
+ * struct test_obj {
+ * [...]
+ * struct rhash_head node;
+ * };
+ *
+ * u32 my_hash_fn(const void *data, u32 len, u32 seed)
+ * {
+ * struct test_obj *obj = data;
+ *
+ * return [... hash ...];
+ * }
+ *
+ * struct rhashtable_params params = {
+ * .head_offset = offsetof(struct test_obj, node),
+ * .hashfn = jhash,
+ * .obj_hashfn = my_hash_fn,
+ * };
+ */
#define rhashtable_init(...) alloc_hooks(rhashtable_init_noprof(__VA_ARGS__))
int __rhltable_init_noprof(struct rhltable *hlt,
const struct rhashtable_params *params,
- struct lock_class_key *key);
+ struct rhashtable_lockdep_keys *keys);
#define rhltable_init_noprof(hlt, params) \
({ \
- static struct lock_class_key __key; \
+ static struct rhashtable_lockdep_keys __keys; \
\
- __rhltable_init_noprof(hlt, params, &__key); \
+ __rhltable_init_noprof(hlt, params, &__keys); \
})
+
+/**
+ * rhltable_init - initialize a new hash list table
+ * @hlt: hash list table to be initialized
+ * @params: configuration parameters
+ *
+ * Initializes a new hash list table.
+ *
+ * See documentation for rhashtable_init.
+ */
#define rhltable_init(...) alloc_hooks(rhltable_init_noprof(__VA_ARGS__))
#endif /* _LINUX_RHASHTABLE_TYPES_H */
diff --git a/include/linux/rhashtable.h b/include/linux/rhashtable.h
index 6c5e6d9accba..ec853c1b9af3 100644
--- a/include/linux/rhashtable.h
+++ b/include/linux/rhashtable.h
@@ -328,8 +328,7 @@ static inline unsigned long rht_lock_nested(struct bucket_table *tbl,
local_irq_save(flags);
bit_spin_lock(0, (unsigned long *)bucket);
- /* subclass 0 is used for ->lock and 1 for ->mutex. 2+ for bitlocks */
- lock_acquire_exclusive(&tbl->dep_map, subclass+2, 0, NULL, _THIS_IP_);
+ lock_acquire_exclusive(&tbl->dep_map, subclass, 0, NULL, _THIS_IP_);
return flags;
}
diff --git a/lib/rhashtable.c b/lib/rhashtable.c
index 5da0e53a8d42..a3a4a1f7751e 100644
--- a/lib/rhashtable.c
+++ b/lib/rhashtable.c
@@ -207,7 +207,6 @@ static struct bucket_table *bucket_table_alloc(struct rhashtable *ht,
return NULL;
#ifdef CONFIG_LOCKDEP
- /* bitlocks must use nesting level 2 or more */
lockdep_init_map(&tbl->dep_map, "rhashtable_bucket", ht->lockdep_key, 0);
#endif
@@ -432,7 +431,7 @@ static void rht_deferred_worker(struct work_struct *work)
int err = 0;
ht = container_of(work, struct rhashtable, run_work);
- mutex_lock_nested(&ht->mutex, 1);
+ mutex_lock(&ht->mutex);
tbl = rht_dereference(ht->tbl, ht);
tbl = rhashtable_last_table(ht, tbl);
@@ -1122,51 +1121,9 @@ static u32 rhashtable_jhash2(const void *key, u32 length, u32 seed)
return jhash2(key, length, seed);
}
-/**
- * rhashtable_init - initialize a new hash table
- * @ht: hash table to be initialized
- * @params: configuration parameters
- *
- * Initializes a new hash table based on the provided configuration
- * parameters. A table can be configured either with a variable or
- * fixed length key:
- *
- * Configuration Example 1: Fixed length keys
- * struct test_obj {
- * int key;
- * void * my_member;
- * struct rhash_head node;
- * };
- *
- * struct rhashtable_params params = {
- * .head_offset = offsetof(struct test_obj, node),
- * .key_offset = offsetof(struct test_obj, key),
- * .key_len = sizeof(int),
- * .hashfn = jhash,
- * };
- *
- * Configuration Example 2: Variable length keys
- * struct test_obj {
- * [...]
- * struct rhash_head node;
- * };
- *
- * u32 my_hash_fn(const void *data, u32 len, u32 seed)
- * {
- * struct test_obj *obj = data;
- *
- * return [... hash ...];
- * }
- *
- * struct rhashtable_params params = {
- * .head_offset = offsetof(struct test_obj, node),
- * .hashfn = jhash,
- * .obj_hashfn = my_hash_fn,
- * };
- */
int __rhashtable_init_noprof(struct rhashtable *ht,
- const struct rhashtable_params *params,
- struct lock_class_key *key)
+ const struct rhashtable_params *params,
+ struct rhashtable_lockdep_keys *keys)
{
struct bucket_table *tbl;
size_t size;
@@ -1176,13 +1133,11 @@ int __rhashtable_init_noprof(struct rhashtable *ht,
return -EINVAL;
memset(ht, 0, sizeof(*ht));
- /* mutex_lock must use nesting level 1 */
- mutex_init_with_key(&ht->mutex, key);
+ mutex_init_with_key(&ht->mutex, &keys->mutex_key);
spin_lock_init(&ht->lock);
- /* spin_lock can use nesting level 0 */
- lockdep_set_class(&ht->lock, key);
+ lockdep_set_class(&ht->lock, &keys->lock_key);
#ifdef CONFIG_LOCKDEP
- ht->lockdep_key = key;
+ ht->lockdep_key = &keys->bucket_key;
#endif
memcpy(&ht->p, params, sizeof(*params));
@@ -1236,22 +1191,13 @@ int __rhashtable_init_noprof(struct rhashtable *ht,
}
EXPORT_SYMBOL_GPL(__rhashtable_init_noprof);
-/**
- * rhltable_init - initialize a new hash list table
- * @hlt: hash list table to be initialized
- * @params: configuration parameters
- *
- * Initializes a new hash list table.
- *
- * See documentation for rhashtable_init.
- */
int __rhltable_init_noprof(struct rhltable *hlt,
const struct rhashtable_params *params,
- struct lock_class_key *key)
+ struct rhashtable_lockdep_keys *keys)
{
int err;
- err = __rhashtable_init_noprof(&hlt->ht, params, key);
+ err = __rhashtable_init_noprof(&hlt->ht, params, keys);
hlt->ht.rhlist = true;
return err;
}
diff --git a/lib/test_rhashtable.c b/lib/test_rhashtable.c
index 85a615e74591..b767a38a74f9 100644
--- a/lib/test_rhashtable.c
+++ b/lib/test_rhashtable.c
@@ -477,7 +477,7 @@ static unsigned int __init print_ht(struct rhltable *rhlt)
ht = &rhlt->ht;
/* Take the mutex to avoid RCU warning */
- mutex_lock_nested(&ht->mutex, 1);
+ mutex_lock(&ht->mutex);
tbl = rht_dereference(ht->tbl, ht);
for (i = 0; i < tbl->size; i++) {
struct rhash_head *pos, *next;
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-09-16 8:47 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-13 1:31 [syzbot] [bridge?] WARNING: locking bug in match_held_lock syzbot
2026-09-15 3:40 ` Shin'ichiro Kawasaki
2026-09-15 4:06 ` Eric Dumazet
2026-09-15 6:04 ` [PATCH] rhashtable: Use separate lockdep keys for each lock Herbert Xu
2026-09-15 21:06 ` NeilBrown
2026-09-16 8:00 ` [v2 PATCH] " Herbert Xu
2026-09-16 8:46 ` [v3 " Herbert Xu
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®