diff options
-rw-r--r-- | kernel/cgroup.c | 63 |
1 files changed, 58 insertions, 5 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 87167e40c4fa..fd684bfd154d 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c | |||
@@ -4426,6 +4426,60 @@ out_err: | |||
4426 | return ret; | 4426 | return ret; |
4427 | } | 4427 | } |
4428 | 4428 | ||
4429 | static void cgroup_procs_release(struct kernfs_open_file *of) | ||
4430 | { | ||
4431 | if (of->priv) { | ||
4432 | css_task_iter_end(of->priv); | ||
4433 | kfree(of->priv); | ||
4434 | } | ||
4435 | } | ||
4436 | |||
4437 | static void *cgroup_procs_next(struct seq_file *s, void *v, loff_t *pos) | ||
4438 | { | ||
4439 | struct kernfs_open_file *of = s->private; | ||
4440 | struct css_task_iter *it = of->priv; | ||
4441 | struct task_struct *task; | ||
4442 | |||
4443 | do { | ||
4444 | task = css_task_iter_next(it); | ||
4445 | } while (task && !thread_group_leader(task)); | ||
4446 | |||
4447 | return task; | ||
4448 | } | ||
4449 | |||
4450 | static void *cgroup_procs_start(struct seq_file *s, loff_t *pos) | ||
4451 | { | ||
4452 | struct kernfs_open_file *of = s->private; | ||
4453 | struct cgroup *cgrp = seq_css(s)->cgroup; | ||
4454 | struct css_task_iter *it = of->priv; | ||
4455 | |||
4456 | /* | ||
4457 | * When a seq_file is seeked, it's always traversed sequentially | ||
4458 | * from position 0, so we can simply keep iterating on !0 *pos. | ||
4459 | */ | ||
4460 | if (!it) { | ||
4461 | if (WARN_ON_ONCE((*pos)++)) | ||
4462 | return ERR_PTR(-EINVAL); | ||
4463 | |||
4464 | it = kzalloc(sizeof(*it), GFP_KERNEL); | ||
4465 | if (!it) | ||
4466 | return ERR_PTR(-ENOMEM); | ||
4467 | of->priv = it; | ||
4468 | css_task_iter_start(&cgrp->self, it); | ||
4469 | } else if (!(*pos)++) { | ||
4470 | css_task_iter_end(it); | ||
4471 | css_task_iter_start(&cgrp->self, it); | ||
4472 | } | ||
4473 | |||
4474 | return cgroup_procs_next(s, NULL, NULL); | ||
4475 | } | ||
4476 | |||
4477 | static int cgroup_procs_show(struct seq_file *s, void *v) | ||
4478 | { | ||
4479 | seq_printf(s, "%d\n", task_tgid_vnr(v)); | ||
4480 | return 0; | ||
4481 | } | ||
4482 | |||
4429 | /* | 4483 | /* |
4430 | * Stuff for reading the 'tasks'/'procs' files. | 4484 | * Stuff for reading the 'tasks'/'procs' files. |
4431 | * | 4485 | * |
@@ -4914,11 +4968,10 @@ static struct cftype cgroup_dfl_base_files[] = { | |||
4914 | { | 4968 | { |
4915 | .name = "cgroup.procs", | 4969 | .name = "cgroup.procs", |
4916 | .file_offset = offsetof(struct cgroup, procs_file), | 4970 | .file_offset = offsetof(struct cgroup, procs_file), |
4917 | .seq_start = cgroup_pidlist_start, | 4971 | .release = cgroup_procs_release, |
4918 | .seq_next = cgroup_pidlist_next, | 4972 | .seq_start = cgroup_procs_start, |
4919 | .seq_stop = cgroup_pidlist_stop, | 4973 | .seq_next = cgroup_procs_next, |
4920 | .seq_show = cgroup_pidlist_show, | 4974 | .seq_show = cgroup_procs_show, |
4921 | .private = CGROUP_FILE_PROCS, | ||
4922 | .write = cgroup_procs_write, | 4975 | .write = cgroup_procs_write, |
4923 | }, | 4976 | }, |
4924 | { | 4977 | { |