diff options
author | Tejun Heo <tj@kernel.org> | 2015-12-03 10:22:52 -0500 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2015-12-03 10:22:52 -0500 |
commit | 8075b542cf9f5d8a6afd92b4a940e29a677a7510 (patch) | |
tree | c2075c5fa70b16d086871edaf94febd954fec073 /kernel/cgroup_pids.c | |
parent | d2b4365809060b256330a99289de9797a5dd6967 (diff) | |
parent | 67cde9c4938945b9510730c64e68d2f1dd7bc0aa (diff) |
Merge branch 'for-4.4-fixes' into for-4.5
Diffstat (limited to 'kernel/cgroup_pids.c')
-rw-r--r-- | kernel/cgroup_pids.c | 77 |
1 files changed, 20 insertions, 57 deletions
diff --git a/kernel/cgroup_pids.c b/kernel/cgroup_pids.c index cdd8df4e991c..b50d5a167fda 100644 --- a/kernel/cgroup_pids.c +++ b/kernel/cgroup_pids.c | |||
@@ -106,7 +106,7 @@ static void pids_uncharge(struct pids_cgroup *pids, int num) | |||
106 | { | 106 | { |
107 | struct pids_cgroup *p; | 107 | struct pids_cgroup *p; |
108 | 108 | ||
109 | for (p = pids; p; p = parent_pids(p)) | 109 | for (p = pids; parent_pids(p); p = parent_pids(p)) |
110 | pids_cancel(p, num); | 110 | pids_cancel(p, num); |
111 | } | 111 | } |
112 | 112 | ||
@@ -123,7 +123,7 @@ static void pids_charge(struct pids_cgroup *pids, int num) | |||
123 | { | 123 | { |
124 | struct pids_cgroup *p; | 124 | struct pids_cgroup *p; |
125 | 125 | ||
126 | for (p = pids; p; p = parent_pids(p)) | 126 | for (p = pids; parent_pids(p); p = parent_pids(p)) |
127 | atomic64_add(num, &p->counter); | 127 | atomic64_add(num, &p->counter); |
128 | } | 128 | } |
129 | 129 | ||
@@ -140,7 +140,7 @@ static int pids_try_charge(struct pids_cgroup *pids, int num) | |||
140 | { | 140 | { |
141 | struct pids_cgroup *p, *q; | 141 | struct pids_cgroup *p, *q; |
142 | 142 | ||
143 | for (p = pids; p; p = parent_pids(p)) { | 143 | for (p = pids; parent_pids(p); p = parent_pids(p)) { |
144 | int64_t new = atomic64_add_return(num, &p->counter); | 144 | int64_t new = atomic64_add_return(num, &p->counter); |
145 | 145 | ||
146 | /* | 146 | /* |
@@ -162,13 +162,13 @@ revert: | |||
162 | return -EAGAIN; | 162 | return -EAGAIN; |
163 | } | 163 | } |
164 | 164 | ||
165 | static int pids_can_attach(struct cgroup_subsys_state *css, | 165 | static int pids_can_attach(struct cgroup_taskset *tset) |
166 | struct cgroup_taskset *tset) | ||
167 | { | 166 | { |
168 | struct pids_cgroup *pids = css_pids(css); | ||
169 | struct task_struct *task; | 167 | struct task_struct *task; |
168 | struct cgroup_subsys_state *dst_css; | ||
170 | 169 | ||
171 | cgroup_taskset_for_each(task, tset) { | 170 | cgroup_taskset_for_each(task, dst_css, tset) { |
171 | struct pids_cgroup *pids = css_pids(dst_css); | ||
172 | struct cgroup_subsys_state *old_css; | 172 | struct cgroup_subsys_state *old_css; |
173 | struct pids_cgroup *old_pids; | 173 | struct pids_cgroup *old_pids; |
174 | 174 | ||
@@ -187,13 +187,13 @@ static int pids_can_attach(struct cgroup_subsys_state *css, | |||
187 | return 0; | 187 | return 0; |
188 | } | 188 | } |
189 | 189 | ||
190 | static void pids_cancel_attach(struct cgroup_subsys_state *css, | 190 | static void pids_cancel_attach(struct cgroup_taskset *tset) |
191 | struct cgroup_taskset *tset) | ||
192 | { | 191 | { |
193 | struct pids_cgroup *pids = css_pids(css); | ||
194 | struct task_struct *task; | 192 | struct task_struct *task; |
193 | struct cgroup_subsys_state *dst_css; | ||
195 | 194 | ||
196 | cgroup_taskset_for_each(task, tset) { | 195 | cgroup_taskset_for_each(task, dst_css, tset) { |
196 | struct pids_cgroup *pids = css_pids(dst_css); | ||
197 | struct cgroup_subsys_state *old_css; | 197 | struct cgroup_subsys_state *old_css; |
198 | struct pids_cgroup *old_pids; | 198 | struct pids_cgroup *old_pids; |
199 | 199 | ||
@@ -205,65 +205,28 @@ static void pids_cancel_attach(struct cgroup_subsys_state *css, | |||
205 | } | 205 | } |
206 | } | 206 | } |
207 | 207 | ||
208 | /* | ||
209 | * task_css_check(true) in pids_can_fork() and pids_cancel_fork() relies | ||
210 | * on threadgroup_change_begin() held by the copy_process(). | ||
211 | */ | ||
208 | static int pids_can_fork(struct task_struct *task, void **priv_p) | 212 | static int pids_can_fork(struct task_struct *task, void **priv_p) |
209 | { | 213 | { |
210 | struct cgroup_subsys_state *css; | 214 | struct cgroup_subsys_state *css; |
211 | struct pids_cgroup *pids; | 215 | struct pids_cgroup *pids; |
212 | int err; | ||
213 | 216 | ||
214 | /* | 217 | css = task_css_check(current, pids_cgrp_id, true); |
215 | * Use the "current" task_css for the pids subsystem as the tentative | ||
216 | * css. It is possible we will charge the wrong hierarchy, in which | ||
217 | * case we will forcefully revert/reapply the charge on the right | ||
218 | * hierarchy after it is committed to the task proper. | ||
219 | */ | ||
220 | css = task_get_css(current, pids_cgrp_id); | ||
221 | pids = css_pids(css); | 218 | pids = css_pids(css); |
222 | 219 | return pids_try_charge(pids, 1); | |
223 | err = pids_try_charge(pids, 1); | ||
224 | if (err) | ||
225 | goto err_css_put; | ||
226 | |||
227 | *priv_p = css; | ||
228 | return 0; | ||
229 | |||
230 | err_css_put: | ||
231 | css_put(css); | ||
232 | return err; | ||
233 | } | 220 | } |
234 | 221 | ||
235 | static void pids_cancel_fork(struct task_struct *task, void *priv) | 222 | static void pids_cancel_fork(struct task_struct *task, void *priv) |
236 | { | 223 | { |
237 | struct cgroup_subsys_state *css = priv; | ||
238 | struct pids_cgroup *pids = css_pids(css); | ||
239 | |||
240 | pids_uncharge(pids, 1); | ||
241 | css_put(css); | ||
242 | } | ||
243 | |||
244 | static void pids_fork(struct task_struct *task, void *priv) | ||
245 | { | ||
246 | struct cgroup_subsys_state *css; | 224 | struct cgroup_subsys_state *css; |
247 | struct cgroup_subsys_state *old_css = priv; | ||
248 | struct pids_cgroup *pids; | 225 | struct pids_cgroup *pids; |
249 | struct pids_cgroup *old_pids = css_pids(old_css); | ||
250 | 226 | ||
251 | css = task_get_css(task, pids_cgrp_id); | 227 | css = task_css_check(current, pids_cgrp_id, true); |
252 | pids = css_pids(css); | 228 | pids = css_pids(css); |
253 | 229 | pids_uncharge(pids, 1); | |
254 | /* | ||
255 | * If the association has changed, we have to revert and reapply the | ||
256 | * charge/uncharge on the wrong hierarchy to the current one. Since | ||
257 | * the association can only change due to an organisation event, its | ||
258 | * okay for us to ignore the limit in this case. | ||
259 | */ | ||
260 | if (pids != old_pids) { | ||
261 | pids_uncharge(old_pids, 1); | ||
262 | pids_charge(pids, 1); | ||
263 | } | ||
264 | |||
265 | css_put(css); | ||
266 | css_put(old_css); | ||
267 | } | 230 | } |
268 | 231 | ||
269 | static void pids_free(struct task_struct *task) | 232 | static void pids_free(struct task_struct *task) |
@@ -335,6 +298,7 @@ static struct cftype pids_files[] = { | |||
335 | { | 298 | { |
336 | .name = "current", | 299 | .name = "current", |
337 | .read_s64 = pids_current_read, | 300 | .read_s64 = pids_current_read, |
301 | .flags = CFTYPE_NOT_ON_ROOT, | ||
338 | }, | 302 | }, |
339 | { } /* terminate */ | 303 | { } /* terminate */ |
340 | }; | 304 | }; |
@@ -346,7 +310,6 @@ struct cgroup_subsys pids_cgrp_subsys = { | |||
346 | .cancel_attach = pids_cancel_attach, | 310 | .cancel_attach = pids_cancel_attach, |
347 | .can_fork = pids_can_fork, | 311 | .can_fork = pids_can_fork, |
348 | .cancel_fork = pids_cancel_fork, | 312 | .cancel_fork = pids_cancel_fork, |
349 | .fork = pids_fork, | ||
350 | .free = pids_free, | 313 | .free = pids_free, |
351 | .legacy_cftypes = pids_files, | 314 | .legacy_cftypes = pids_files, |
352 | .dfl_cftypes = pids_files, | 315 | .dfl_cftypes = pids_files, |