hulk inclusion category: bugfix bugzilla: -------------------------------- Spin lock pidns_list_lock is used in both process context and bottom half, which may cause the AA deadlock issue. Replace spin_lock with spin_lock_bh to resolve this problem. Call trace: native_queued_spin_lock_slowpath+0x71/0x428 destroy_pid_namespace+0x100/0x110 put_pid_ns+0x90/0xc8 put_pid+0x8c/0xc8 delayed_put_pid+0x1c/0x30 rcu_do_batch+0x164/0x580 rcu_core+0x130/0x2b8 rcu_core_si+0x18/0x30 handle_softirqs+0x120/0x328 __do_softirq+0x1c/0x28 ____do_softirq+0x18/0x30 call_on_irq_stack+0x30/0x48 do_softirq_own_stack+0x24/0x38 irq_exit_rcu+0x108/0x130 el1_interrupt+0x54/0x130 el1h_64_irq_handler+0x24/0x30 el1h_64_irq+0x78/0x80 create_pid_namespace+0x214/0x3c0 copy_pid_ns+0x90/0xf0 create_new_namespaces+0xc8/0x368 unshare_nsproxy_namespaces+0x6c/0xc0 ksys_unshare+0x130/0x418 __arm64_sys_unshare+0x1c/0x38 invoke_syscall+0x50/0x128 el0_svc_common.constprop.0+0x48/0xf0 do_el0_svc+0x24/0x38 el0_svc+0x44/0x1e8 el0t_64_sync_handler+0xc0/0xc8 el0t_64_sync+0x3c8/0x3d0 Fixes: d758abf3762c ("bpf-rvi: pidns: Calculate loadavg for each pid namespace") Signed-off-by: Gu Bowen <gubowen5@huawei.com> --- kernel/pid_namespace.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/kernel/pid_namespace.c b/kernel/pid_namespace.c index b321c02f382e..0bfd9ff3a6b8 100644 --- a/kernel/pid_namespace.c +++ b/kernel/pid_namespace.c @@ -128,9 +128,9 @@ static struct pid_namespace *create_pid_namespace(struct user_namespace *user_ns ns->loadavg = kmem_cache_zalloc(pidns_loadavg_cachep, GFP_KERNEL); if (ns->loadavg == NULL) goto out_free_idr; - spin_lock(&pidns_list_lock); + spin_lock_bh(&pidns_list_lock); list_add_tail(&ns->loadavg->list, &init_pidns_loadavg.list); - spin_unlock(&pidns_list_lock); + spin_unlock_bh(&pidns_list_lock); #endif return ns; @@ -164,9 +164,9 @@ static void destroy_pid_namespace(struct pid_namespace *ns) * ns->loadavg's lifecycle aligns precisely with ns, * so don't need RCU delayed free. */ - spin_lock(&pidns_list_lock); + spin_lock_bh(&pidns_list_lock); list_del(&ns->loadavg->list); - spin_unlock(&pidns_list_lock); + spin_unlock_bh(&pidns_list_lock); kmem_cache_free(pidns_loadavg_cachep, ns->loadavg); #endif call_rcu(&ns->rcu, delayed_free_pidns); @@ -537,13 +537,13 @@ static void pidns_list_reset(void) { struct list_head *pos, *tmp; - spin_lock(&pidns_list_lock); + spin_lock_bh(&pidns_list_lock); list_for_each_safe(pos, tmp, &init_pidns_loadavg.list) { struct pidns_loadavg *entry = list_entry(pos, struct pidns_loadavg, list); entry->load_tasks = 0; // reset } - spin_unlock(&pidns_list_lock); + spin_unlock_bh(&pidns_list_lock); } static void pidns_update_load_tasks(void) @@ -574,7 +574,7 @@ static void pidns_calc_avenrun(void) { struct list_head *pos; - spin_lock(&pidns_list_lock); + spin_lock_bh(&pidns_list_lock); /* * As the loadavg of init_pid_ns is exactly /proc/loadavg, avoid redundant * re-calculation for init_pid_ns, and reuse init_pidns_loadavg.list as the @@ -590,7 +590,7 @@ static void pidns_calc_avenrun(void) entry->avenrun[1] = calc_load(entry->avenrun[1], EXP_5, active); entry->avenrun[2] = calc_load(entry->avenrun[2], EXP_15, active); } - spin_unlock(&pidns_list_lock); + spin_unlock_bh(&pidns_list_lock); } static void pidns_calc_loadavg_workfn(struct work_struct *work) -- 2.43.0