Re: [PATCH 1/3] task: Add a count of task rcu users

From: Frederic Weisbecker
Date: Wed Sep 04 2019 - 10:44:21 EST


On Mon, Sep 02, 2019 at 11:51:34PM -0500, Eric W. Biederman wrote:
>
> Add a count of the number of rcu users (currently 1) of the task
> struct so that we can later add the scheduler case and get rid of the
> very subtle task_rcu_dereference, and just use rcu_dereference.
>
> As suggested by Oleg have the count overlap rcu_head so that no
> additional space in task_struct is required.
>
> Inspired-by: Linus Torvalds <torvalds@xxxxxxxxxxxxxxxxxxxx>
> Inspired-by: Oleg Nesterov <oleg@xxxxxxxxxx>
> Signed-off-by: "Eric W. Biederman" <ebiederm@xxxxxxxxxxxx>
> ---
> include/linux/sched.h | 5 ++++-
> include/linux/sched/task.h | 1 +
> kernel/exit.c | 7 ++++++-
> kernel/fork.c | 7 +++----
> 4 files changed, 14 insertions(+), 6 deletions(-)
>
> diff --git a/include/linux/sched.h b/include/linux/sched.h
> index 9f51932bd543..99a4518b9b17 100644
> --- a/include/linux/sched.h
> +++ b/include/linux/sched.h
> @@ -1142,7 +1142,10 @@ struct task_struct {
>
> struct tlbflush_unmap_batch tlb_ubc;
>
> - struct rcu_head rcu;
> + union {
> + refcount_t rcu_users;
> + struct rcu_head rcu;

So what happens if, say:


CPU 1 CPU 2
--------------------------------------------------------------
rcu_read_lock()
p = rcu_dereference(rq->task)
if (refcount_inc_not_zero(p->rcu_users)) {
.....
release_task() {
put_task_struct_rcu_user() {
call_rcu() {
queue rcu_head
}
}
}
put_task_struct_rcu_user(); //here rcu_users has been overwritten


Thanks.