hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/release-management/issues/ID5CMS -------------------------------- In DT qemu environment, when we running the detach xcall testcase, panic happened. Calltrace is BUG: scheduling while atomic: bash/293/0x00000002 Modules linked in: dynamic_xcall_test(C) CPU: 1 PID: 293 Comm: bash Tainted: GC 6.6.0-g49eee28051c5 #1 Hardware name: linux,dummy-virt (DT) Call trace: dump_backtrace+0x98/0xf8 show_stack+0x1c/0x30 dump_stack_lvl+0x44/0x58 dump_stack+0x14/0x20 __schedule_bug+0x54/0x70 __schedule+0x754/0x898 schedule+0x60/0x138 p9_client_rpc+0x118/0x430 p9_client_clunk+0x48/0xa8 v9fs_dentry_release+0x118/0x138 __dentry_kill+0x130/0x208 dput+0x25c/0x488 path_put+0x20/0x40 free_xcall_comm.part.0+0x38/0x58 free_xcall_comm+0x18/0x30 put_xcall+0x7c/0xc0 xcall_detach+0x68/0xc0 proc_xcall_command+0x188/0x1d8 xcall_comm_write+0x78/0x100 proc_reg_write+0x78/0xf8 vfs_write+0x160/0x480 ksys_write+0x70/0x108 __arm64_sys_write+0x20/0x30 invoke_syscall+0x48/0x110 el0_svc_common.constprop.0+0x44/0xe8 do_el0_svc+0x84/0xc8 el0_slow_syscall+0x3c/0x120 .slow_syscall+0x16c/0x170 In xcall_detach(), there are two put_xcall(). The first one pairs with find_xcall(), this one only decrease the refcount. The second one pairs with list_del(), this one will release resources. All of them are protected by xcall_list_lock. While the second put_xcall() call path_put(), it may call schedule() depends on the related filesystem. Schedule in spinlock context, this is why the panic happen. Move the second put_xcall() out of spinlock context to solve this issue. Fixes: e8bc47c7369e ("xcall2.0: Fix mem leak in proc_xcall_command") Signed-off-by: Xinyu Zheng <zhengxinyu6@huawei.com> --- arch/arm64/kernel/xcall/core.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/arm64/kernel/xcall/core.c b/arch/arm64/kernel/xcall/core.c index 18b73c044a8d..932452480f0f 100644 --- a/arch/arm64/kernel/xcall/core.c +++ b/arch/arm64/kernel/xcall/core.c @@ -343,8 +343,10 @@ int xcall_detach(struct xcall_comm *comm) put_xcall(xcall); list_del(&xcall->list); - put_xcall(xcall); spin_unlock(&xcall_list_lock); + + // this put_xcall pairs with list_del(&xcall->list) above + put_xcall(xcall); return 0; } -- 2.34.1