From: Andrei Vagin <[email protected]> task_work_run() has to be called before exit_task_namespaces(), because fuse_abort_conn() is called from __fput(). If it will not be executed, we can hang in request_wait_answer(). We have seen this situation when a process was the last member of a mount namespace and the mount namespace has a vstorage fuse mount.
https://jira.sw.ru/browse/PSBM-68266 Signed-off-by: Andrei Vagin <[email protected]> --- include/linux/task_work.h | 9 +++++++-- kernel/exit.c | 9 +++++++++ kernel/task_work.c | 4 ++-- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/include/linux/task_work.h b/include/linux/task_work.h index ca5a1cf..b3af76d 100644 --- a/include/linux/task_work.h +++ b/include/linux/task_work.h @@ -14,11 +14,16 @@ init_task_work(struct callback_head *twork, task_work_func_t func) int task_work_add(struct task_struct *task, struct callback_head *twork, bool); struct callback_head *task_work_cancel(struct task_struct *, task_work_func_t); -void task_work_run(void); +void __task_work_run(bool exiting); + +static inline void task_work_run(void) +{ + return __task_work_run(false); +} static inline void exit_task_work(struct task_struct *task) { - task_work_run(); + __task_work_run(true); } #endif /* _LINUX_TASK_WORK_H */ diff --git a/kernel/exit.c b/kernel/exit.c index 3c83db2..ea54a73 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -827,6 +827,15 @@ void do_exit(long code) exit_fs(tsk); if (group_dead) disassociate_ctty(1); + + /* + * task_work_run() has to be called before exit_task_namespaces(), + * because fuse_abort_conn() is called from __fput(). If it will not + * be executed, we can hang in request_wait_answer(). We have seen this + * situation when a process was the last member of a mount namespace + * and the mount namespace has a vstorage fuse mount. + */ + task_work_run(); exit_task_namespaces(tsk); exit_task_work(tsk); diff --git a/kernel/task_work.c b/kernel/task_work.c index 65bd3c9..f0000c4 100644 --- a/kernel/task_work.c +++ b/kernel/task_work.c @@ -46,7 +46,7 @@ task_work_cancel(struct task_struct *task, task_work_func_t func) return work; } -void task_work_run(void) +void __task_work_run(bool exiting) { struct task_struct *task = current; struct callback_head *work, *head, *next; @@ -58,7 +58,7 @@ void task_work_run(void) */ do { work = ACCESS_ONCE(task->task_works); - head = !work && (task->flags & PF_EXITING) ? + head = !work && exiting ? &work_exited : NULL; } while (cmpxchg(&task->task_works, work, head) != work); -- 1.8.3.1 _______________________________________________ Devel mailing list [email protected] https://lists.openvz.org/mailman/listinfo/devel
