lockdep gets confused with the nested locking: ============================================ WARNING: possible recursive locking detected 6.9.0-rc1-00060-ged3ccc57b108-dirty #6140 Not tainted -------------------------------------------- drgn/455 is trying to acquire lock: ffff0000c00131d0 (&vn->busy.lock/1){+.+.}-{2:2}, at: find_vmap_area_exceed_addr_lock+0x64/0x124 but task is already holding lock: ffff0000c0011878 (&vn->busy.lock/1){+.+.}-{2:2}, at: find_vmap_area_exceed_addr_lock+0x64/0x124 other info that might help us debug this: Possible unsafe locking scenario: CPU0 ---- lock(&vn->busy.lock/1); lock(&vn->busy.lock/1); *** DEADLOCK *** May be due to missing lock nesting notation 3 locks held by drgn/455: #0: ffff800081ecbba8 (kclist_lock){++++}-{3:3}, at: read_kcore_iter+0x5c/0xa24 #1: ffff800081ea7688 (page_offline_rwsem){.+.+}-{3:3}, at: page_offline_freeze+0x14/0x1c #2: ffff0000c0011878 (&vn->busy.lock/1){+.+.}-{2:2}, at: find_vmap_area_exceed_addr_lock+0x64/0x124 stack backtrace: CPU: 5 PID: 455 Comm: drgn Not tainted 6.9.0-rc1-00060-ged3ccc57b108-dirty #6140 Hardware name: linux,dummy-virt (DT) Call trace: dump_backtrace+0x90/0xe4 show_stack+0x14/0x1c dump_stack_lvl+0x84/0xc0 dump_stack+0x14/0x1c print_deadlock_bug+0x24c/0x334 __lock_acquire+0xdf4/0x20e0 lock_acquire+0x204/0x330 _raw_spin_lock_nested+0x40/0x54 find_vmap_area_exceed_addr_lock+0x64/0x124 vread_iter+0x44/0x428 read_kcore_iter+0x170/0xa24 proc_reg_read_iter+0x7c/0xcc vfs_read+0x220/0x2c4 ksys_pread64+0x74/0xb4 __arm64_sys_pread64+0x1c/0x24 invoke_syscall+0x44/0x104 el0_svc_common.constprop.0+0xb4/0xd4 do_el0_svc+0x18/0x20 el0_svc+0x44/0x108 el0t_64_sync_handler+0x118/0x124 el0t_64_sync+0x168/0x16c which seems to be because it's missing the proper nested annotation. Add the level annotation to make lockdep happy about this use case. Fixes: 53becf32aec1 ("mm: vmalloc: support multiple nodes in vread_iter") Signed-off-by: Jens Axboe <axboe@xxxxxxxxx> --- diff --git a/mm/vmalloc.c b/mm/vmalloc.c index 22aa63f4ef63..26a69fa6809c 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -1032,7 +1032,7 @@ find_vmap_area_exceed_addr_lock(unsigned long addr, struct vmap_area **va) for (i = 0; i < nr_vmap_nodes; i++) { vn = &vmap_nodes[i]; - spin_lock(&vn->busy.lock); + spin_lock_nested(&vn->busy.lock, i); va_lowest = __find_vmap_area_exceed_addr(addr, &vn->busy.root); if (va_lowest) { if (!va_node || va_lowest->va_start < (*va)->va_start) { -- Jens Axboe