
hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IBN6HC -------------------------------- Since the commit c8903ef0769e switched task_work to the IPI method for updating the task's partid, this may cause a deadlock on the tasklist_lock when updating the control group's rmid. The concurrent scenario is that on one side, a read lock on the tasklist_lock is obtained and tries to update rmid of a control group by IPI method, while on the other side, a task in this control group, while waiting for a child thread to exit, disables interrupts and attempts to obtain a write lock on the tasklist_lock, resulting in a deadlock because it cannot respond to the IPI interrupt right now. CPU_A CPU_B resctrl_group_rmid_write() read_lock(&tasklist_lock); <-- read locked do_wait() wait_consider_task() wait_task_zombie() release_task() write_lock_irq(&tasklist_lock); __raw_write_lock_irq(lock); local_irq_disable(); <-- disable interrupt do_raw_write_lock() <-- wait write lock __resctrl_group_move_task(t, rdtgrp); update_task_closid_rmid(tsk); smp_call_function_single(); <-- never return The IPI operation needs to be moved outside the critical section of the tasklist_lock. We have chosen to merge it with the subsequent update_closid_rmid(). Instead of just binding to the specified CPUs of the control group, but all online CPUs. Fixes: c8903ef0769e ("[Huawei] arm64/mpam: Use an IPI instead of task_work_add() to update MPAM sysreg") Signed-off-by: Zeng Heng <zengheng4@huawei.com> --- arch/arm64/kernel/mpam/mpam_resctrl.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/arch/arm64/kernel/mpam/mpam_resctrl.c b/arch/arm64/kernel/mpam/mpam_resctrl.c index ab822fd6828d..220dc48e3614 100644 --- a/arch/arm64/kernel/mpam/mpam_resctrl.c +++ b/arch/arm64/kernel/mpam/mpam_resctrl.c @@ -1344,8 +1344,8 @@ static void update_task_closid_rmid(struct task_struct *t) _update_task_closid_rmid(t); } -int __resctrl_group_move_task(struct task_struct *tsk, - struct rdtgroup *rdtgrp) +static int resctrl_group_update_task(struct task_struct *tsk, + struct rdtgroup *rdtgrp) { /* * Set the task's closid/rmid before the MPAM sysreg can be @@ -1376,6 +1376,18 @@ int __resctrl_group_move_task(struct task_struct *tsk, */ smp_mb(); + return 0; +} + +int __resctrl_group_move_task(struct task_struct *tsk, + struct rdtgroup *rdtgrp) +{ + int err; + + err = resctrl_group_update_task(tsk, rdtgrp); + if (err) + return err; + /* * By now, the task's closid and rmid are set. If the task is current * on a CPU, the MPAM sysreg needs to be updated to make the resource @@ -1972,7 +1984,7 @@ static ssize_t resctrl_group_rmid_write(struct kernfs_open_file *of, read_lock(&tasklist_lock); for_each_process_thread(p, t) { if (t->closid == rdtgrp->closid.intpartid) { - ret = __resctrl_group_move_task(t, rdtgrp); + ret = resctrl_group_update_task(t, rdtgrp); if (ret) { read_unlock(&tasklist_lock); goto rollback; @@ -1981,7 +1993,7 @@ static ssize_t resctrl_group_rmid_write(struct kernfs_open_file *of, } read_unlock(&tasklist_lock); - update_closid_rmid(&rdtgrp->cpu_mask, rdtgrp); + update_closid_rmid(cpu_online_mask, rdtgrp); rmid_free(old_rmid); unlock: @@ -2004,7 +2016,7 @@ static ssize_t resctrl_group_rmid_write(struct kernfs_open_file *of, read_lock(&tasklist_lock); for_each_process_thread(p, t) { if (t->closid == rdtgrp->closid.intpartid) - WARN_ON_ONCE(__resctrl_group_move_task(t, rdtgrp)); + WARN_ON_ONCE(resctrl_group_update_task(t, rdtgrp)); } read_unlock(&tasklist_lock); -- 2.25.1