[v10,0/2] kernel/fork: beware of __put_task_struct calling context

Message ID 20230614122323.37957-1-wander@redhat.com
Headers
Series kernel/fork: beware of __put_task_struct calling context |

Message

Wander Lairson Costa June 14, 2023, 12:23 p.m. UTC
  Under PREEMPT_RT, __put_task_struct() indirectly acquires sleeping
locks. Therefore, it can't be called from an non-preemptible context.

Instead of calling __put_task_struct() directly, we defer it using
call_rcu(). A more natural approach would use a workqueue, but since
in PREEMPT_RT, we can't allocate dynamic memory from atomic context,
the code would become more complex because we would need to put the
work_struct instance in the task_struct and initialize it when we
allocate a new task_struct.

Changelog
=========

v1:
* Initial implementation fixing the splat.

v2:
* Isolate the logic in its own function.
* Fix two more cases caught in review.

v3:
* Change __put_task_struct() to handle the issue internally.

v4:
* Explain why call_rcu() is safe to call from interrupt context.

v5:
* Explain why __put_task_struct() doesn't conflict with
  put_task_sruct_rcu_user.

v6:
* As per Sebastian's review, revert back the implementation of v2
  with a distinct function.
* Add a check in put_task_struct() to warning when called from a
  non-sleepable context.
* Address more call sites.

v7:
* Fix typos.
* Add an explanation why the new function doesn't conflict with
  delayed_free_task().

v8:
* Bring back v5.
* Fix coding style.

v9:
* Reorganize to not need ___put_task_struct() by Oleg's suggestion.

v10:
* Add a patch preventing a splat when compile with
CONFIG_PROVE_RAW_LOCK_NESTING.

Reported-by: Hu Chunyu <chuhu@redhat.com>
Suggested-by: Oleg Nesterov <oleg@redhat.com>
Suggested-by: Valentin Schneider <vschneid@redhat.com>
Suggested-by: Peter Zijlstra <peterz@infradead.org>
Cc: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Cc: Paul McKenney <paulmck@kernel.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Luis Goncalves <lgoncalv@redhat.com>

Wander Lairson Costa (2):
  kernel/fork: beware of __put_task_struct calling context
  sched: avoid false lockdep splat in put_task_struct()

 include/linux/sched/task.h | 38 +++++++++++++++++++++++++++++++++++++-
 kernel/fork.c              |  8 ++++++++
 2 files changed, 45 insertions(+), 1 deletion(-)
  

Comments

Peter Zijlstra June 19, 2023, 11:07 a.m. UTC | #1
On Wed, Jun 14, 2023 at 09:23:20AM -0300, Wander Lairson Costa wrote:
> Under PREEMPT_RT, __put_task_struct() indirectly acquires sleeping
> locks. Therefore, it can't be called from an non-preemptible context.
> 
> Instead of calling __put_task_struct() directly, we defer it using
> call_rcu(). A more natural approach would use a workqueue, but since
> in PREEMPT_RT, we can't allocate dynamic memory from atomic context,
> the code would become more complex because we would need to put the
> work_struct instance in the task_struct and initialize it when we
> allocate a new task_struct.

> 
> Wander Lairson Costa (2):
>   kernel/fork: beware of __put_task_struct calling context
>   sched: avoid false lockdep splat in put_task_struct()

Thanks!