diff options
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, |
