diff options
Diffstat (limited to 'kernel/sched/auto_group.c')
-rw-r--r-- | kernel/sched/auto_group.c | 23 |
1 files changed, 12 insertions, 11 deletions
diff --git a/kernel/sched/auto_group.c b/kernel/sched/auto_group.c index 750ed601ddf7..8620fd01b3d0 100644 --- a/kernel/sched/auto_group.c +++ b/kernel/sched/auto_group.c | |||
@@ -111,14 +111,11 @@ bool task_wants_autogroup(struct task_struct *p, struct task_group *tg) | |||
111 | { | 111 | { |
112 | if (tg != &root_task_group) | 112 | if (tg != &root_task_group) |
113 | return false; | 113 | return false; |
114 | |||
115 | /* | 114 | /* |
116 | * We can only assume the task group can't go away on us if | 115 | * If we race with autogroup_move_group() the caller can use the old |
117 | * autogroup_move_group() can see us on ->thread_group list. | 116 | * value of signal->autogroup but in this case sched_move_task() will |
117 | * be called again before autogroup_kref_put(). | ||
118 | */ | 118 | */ |
119 | if (p->flags & PF_EXITING) | ||
120 | return false; | ||
121 | |||
122 | return true; | 119 | return true; |
123 | } | 120 | } |
124 | 121 | ||
@@ -138,13 +135,17 @@ autogroup_move_group(struct task_struct *p, struct autogroup *ag) | |||
138 | } | 135 | } |
139 | 136 | ||
140 | p->signal->autogroup = autogroup_kref_get(ag); | 137 | p->signal->autogroup = autogroup_kref_get(ag); |
141 | 138 | /* | |
142 | if (!READ_ONCE(sysctl_sched_autogroup_enabled)) | 139 | * We can't avoid sched_move_task() after we changed signal->autogroup, |
143 | goto out; | 140 | * this process can already run with task_group() == prev->tg or we can |
144 | 141 | * race with cgroup code which can read autogroup = prev under rq->lock. | |
142 | * In the latter case for_each_thread() can not miss a migrating thread, | ||
143 | * cpu_cgroup_attach() must not be possible after cgroup_exit() and it | ||
144 | * can't be removed from thread list, we hold ->siglock. | ||
145 | */ | ||
145 | for_each_thread(p, t) | 146 | for_each_thread(p, t) |
146 | sched_move_task(t); | 147 | sched_move_task(t); |
147 | out: | 148 | |
148 | unlock_task_sighand(p, &flags); | 149 | unlock_task_sighand(p, &flags); |
149 | autogroup_kref_put(prev); | 150 | autogroup_kref_put(prev); |
150 | } | 151 | } |