Skip to content

Commit ee29720

Browse files
xtfengtorvalds
authored andcommitted
proc: fix inconsistent lock state
Lockdep found an inconsistent lock state when rcu is processing delayed work in softirq. Currently, kernel is using spin_lock/spin_unlock to protect proc_inum_ida, but proc_free_inum is called by rcu in softirq context. Use spin_lock_bh/spin_unlock_bh fix following lockdep warning. ================================= [ INFO: inconsistent lock state ] 3.7.0 torvalds#36 Not tainted --------------------------------- inconsistent {SOFTIRQ-ON-W} -> {IN-SOFTIRQ-W} usage. swapper/1/0 [HC0[0]:SC1[1]:HE1:SE0] takes: (proc_inum_lock){+.?...}, at: proc_free_inum+0x1c/0x50 {SOFTIRQ-ON-W} state was registered at: __lock_acquire+0x8ae/0xca0 lock_acquire+0x199/0x200 _raw_spin_lock+0x41/0x50 proc_alloc_inum+0x4c/0xd0 alloc_mnt_ns+0x49/0xc0 create_mnt_ns+0x25/0x70 mnt_init+0x161/0x1c7 vfs_caches_init+0x107/0x11a start_kernel+0x348/0x38c x86_64_start_reservations+0x131/0x136 x86_64_start_kernel+0x103/0x112 irq event stamp: 2993422 hardirqs last enabled at (2993422): _raw_spin_unlock_irqrestore+0x55/0x80 hardirqs last disabled at (2993421): _raw_spin_lock_irqsave+0x29/0x70 softirqs last enabled at (2993394): _local_bh_enable+0x13/0x20 softirqs last disabled at (2993395): call_softirq+0x1c/0x30 other info that might help us debug this: Possible unsafe locking scenario: CPU0 ---- lock(proc_inum_lock); <Interrupt> lock(proc_inum_lock); *** DEADLOCK *** no locks held by swapper/1/0. stack backtrace: Pid: 0, comm: swapper/1 Not tainted 3.7.0 torvalds#36 Call Trace: <IRQ> [<ffffffff810a40f1>] ? vprintk_emit+0x471/0x510 print_usage_bug+0x2a5/0x2c0 mark_lock+0x33b/0x5e0 __lock_acquire+0x813/0xca0 lock_acquire+0x199/0x200 _raw_spin_lock+0x41/0x50 proc_free_inum+0x1c/0x50 free_pid_ns+0x1c/0x50 put_pid_ns+0x2e/0x50 put_pid+0x4a/0x60 delayed_put_pid+0x12/0x20 rcu_process_callbacks+0x462/0x790 __do_softirq+0x1b4/0x3b0 call_softirq+0x1c/0x30 do_softirq+0x59/0xd0 irq_exit+0x54/0xd0 smp_apic_timer_interrupt+0x95/0xa3 apic_timer_interrupt+0x72/0x80 cpuidle_enter_tk+0x10/0x20 cpuidle_enter_state+0x17/0x50 cpuidle_idle_call+0x287/0x520 cpu_idle+0xba/0x130 start_secondary+0x2b3/0x2bc Signed-off-by: Xiaotian Feng <[email protected]> Cc: Al Viro <[email protected]> Cc: "Eric W. Biederman" <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent c4e1849 commit ee29720

File tree

1 file changed

+6
-6
lines changed

1 file changed

+6
-6
lines changed

fs/proc/generic.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -359,18 +359,18 @@ int proc_alloc_inum(unsigned int *inum)
359359
if (!ida_pre_get(&proc_inum_ida, GFP_KERNEL))
360360
return -ENOMEM;
361361

362-
spin_lock(&proc_inum_lock);
362+
spin_lock_bh(&proc_inum_lock);
363363
error = ida_get_new(&proc_inum_ida, &i);
364-
spin_unlock(&proc_inum_lock);
364+
spin_unlock_bh(&proc_inum_lock);
365365
if (error == -EAGAIN)
366366
goto retry;
367367
else if (error)
368368
return error;
369369

370370
if (i > UINT_MAX - PROC_DYNAMIC_FIRST) {
371-
spin_lock(&proc_inum_lock);
371+
spin_lock_bh(&proc_inum_lock);
372372
ida_remove(&proc_inum_ida, i);
373-
spin_unlock(&proc_inum_lock);
373+
spin_unlock_bh(&proc_inum_lock);
374374
return -ENOSPC;
375375
}
376376
*inum = PROC_DYNAMIC_FIRST + i;
@@ -379,9 +379,9 @@ int proc_alloc_inum(unsigned int *inum)
379379

380380
void proc_free_inum(unsigned int inum)
381381
{
382-
spin_lock(&proc_inum_lock);
382+
spin_lock_bh(&proc_inum_lock);
383383
ida_remove(&proc_inum_ida, inum - PROC_DYNAMIC_FIRST);
384-
spin_unlock(&proc_inum_lock);
384+
spin_unlock_bh(&proc_inum_lock);
385385
}
386386

387387
static void *proc_follow_link(struct dentry *dentry, struct nameidata *nd)

0 commit comments

Comments
 (0)