diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-10-14 15:18:50 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-10-14 15:18:50 -0400 |
| commit | f34d3606f76a8121b9d4940d2dd436bebeb2f9d7 (patch) | |
| tree | 61a9deb6a950568df274580fbbd44a7015af9f7c /kernel | |
| parent | b6daa51b9a6a02a644dcf6b880fd50c1f70ec07f (diff) | |
| parent | bbb427e342495df1cda10051d0566388697499c0 (diff) | |
Merge branch 'for-4.9' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup
Pull cgroup updates from Tejun Heo:
- tracepoints for basic cgroup management operations added
- kernfs and cgroup path formatting functions updated to behave in the
style of strlcpy()
- non-critical bug fixes
* 'for-4.9' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup:
blkcg: Unlock blkcg_pol_mutex only once when cpd == NULL
cgroup: fix error handling regressions in proc_cgroup_show() and cgroup_release_agent()
cpuset: fix error handling regression in proc_cpuset_show()
cgroup: add tracepoints for basic operations
cgroup: make cgroup_path() and friends behave in the style of strlcpy()
kernfs: remove kernfs_path_len()
kernfs: make kernfs_path*() behave in the style of strlcpy()
kernfs: add dummy implementation of kernfs_path_from_node()
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/cgroup.c | 75 | ||||
| -rw-r--r-- | kernel/cpuset.c | 13 | ||||
| -rw-r--r-- | kernel/sched/debug.c | 3 |
3 files changed, 57 insertions, 34 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 44066158f0d1..85bc9beb046d 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c | |||
| @@ -64,6 +64,9 @@ | |||
| 64 | #include <linux/file.h> | 64 | #include <linux/file.h> |
| 65 | #include <net/sock.h> | 65 | #include <net/sock.h> |
| 66 | 66 | ||
| 67 | #define CREATE_TRACE_POINTS | ||
| 68 | #include <trace/events/cgroup.h> | ||
| 69 | |||
| 67 | /* | 70 | /* |
| 68 | * pidlists linger the following amount before being destroyed. The goal | 71 | * pidlists linger the following amount before being destroyed. The goal |
| 69 | * is avoiding frequent destruction in the middle of consecutive read calls | 72 | * is avoiding frequent destruction in the middle of consecutive read calls |
| @@ -1176,6 +1179,8 @@ static void cgroup_destroy_root(struct cgroup_root *root) | |||
| 1176 | struct cgroup *cgrp = &root->cgrp; | 1179 | struct cgroup *cgrp = &root->cgrp; |
| 1177 | struct cgrp_cset_link *link, *tmp_link; | 1180 | struct cgrp_cset_link *link, *tmp_link; |
| 1178 | 1181 | ||
| 1182 | trace_cgroup_destroy_root(root); | ||
| 1183 | |||
| 1179 | cgroup_lock_and_drain_offline(&cgrp_dfl_root.cgrp); | 1184 | cgroup_lock_and_drain_offline(&cgrp_dfl_root.cgrp); |
| 1180 | 1185 | ||
| 1181 | BUG_ON(atomic_read(&root->nr_cgrps)); | 1186 | BUG_ON(atomic_read(&root->nr_cgrps)); |
| @@ -1874,6 +1879,9 @@ static int cgroup_remount(struct kernfs_root *kf_root, int *flags, char *data) | |||
| 1874 | strcpy(root->release_agent_path, opts.release_agent); | 1879 | strcpy(root->release_agent_path, opts.release_agent); |
| 1875 | spin_unlock(&release_agent_path_lock); | 1880 | spin_unlock(&release_agent_path_lock); |
| 1876 | } | 1881 | } |
| 1882 | |||
| 1883 | trace_cgroup_remount(root); | ||
| 1884 | |||
| 1877 | out_unlock: | 1885 | out_unlock: |
| 1878 | kfree(opts.release_agent); | 1886 | kfree(opts.release_agent); |
| 1879 | kfree(opts.name); | 1887 | kfree(opts.name); |
| @@ -2031,6 +2039,8 @@ static int cgroup_setup_root(struct cgroup_root *root, u16 ss_mask) | |||
| 2031 | if (ret) | 2039 | if (ret) |
| 2032 | goto destroy_root; | 2040 | goto destroy_root; |
| 2033 | 2041 | ||
| 2042 | trace_cgroup_setup_root(root); | ||
| 2043 | |||
| 2034 | /* | 2044 | /* |
| 2035 | * There must be no failure case after here, since rebinding takes | 2045 | * There must be no failure case after here, since rebinding takes |
| 2036 | * care of subsystems' refcounts, which are explicitly dropped in | 2046 | * care of subsystems' refcounts, which are explicitly dropped in |
| @@ -2315,22 +2325,18 @@ static struct file_system_type cgroup2_fs_type = { | |||
| 2315 | .fs_flags = FS_USERNS_MOUNT, | 2325 | .fs_flags = FS_USERNS_MOUNT, |
| 2316 | }; | 2326 | }; |
| 2317 | 2327 | ||
| 2318 | static char *cgroup_path_ns_locked(struct cgroup *cgrp, char *buf, size_t buflen, | 2328 | static int cgroup_path_ns_locked(struct cgroup *cgrp, char *buf, size_t buflen, |
| 2319 | struct cgroup_namespace *ns) | 2329 | struct cgroup_namespace *ns) |
| 2320 | { | 2330 | { |
| 2321 | struct cgroup *root = cset_cgroup_from_root(ns->root_cset, cgrp->root); | 2331 | struct cgroup *root = cset_cgroup_from_root(ns->root_cset, cgrp->root); |
| 2322 | int ret; | ||
| 2323 | 2332 | ||
| 2324 | ret = kernfs_path_from_node(cgrp->kn, root->kn, buf, buflen); | 2333 | return kernfs_path_from_node(cgrp->kn, root->kn, buf, buflen); |
| 2325 | if (ret < 0 || ret >= buflen) | ||
| 2326 | return NULL; | ||
| 2327 | return buf; | ||
| 2328 | } | 2334 | } |
| 2329 | 2335 | ||
| 2330 | char *cgroup_path_ns(struct cgroup *cgrp, char *buf, size_t buflen, | 2336 | int cgroup_path_ns(struct cgroup *cgrp, char *buf, size_t buflen, |
| 2331 | struct cgroup_namespace *ns) | 2337 | struct cgroup_namespace *ns) |
| 2332 | { | 2338 | { |
| 2333 | char *ret; | 2339 | int ret; |
| 2334 | 2340 | ||
| 2335 | mutex_lock(&cgroup_mutex); | 2341 | mutex_lock(&cgroup_mutex); |
| 2336 | spin_lock_irq(&css_set_lock); | 2342 | spin_lock_irq(&css_set_lock); |
| @@ -2357,12 +2363,12 @@ EXPORT_SYMBOL_GPL(cgroup_path_ns); | |||
| 2357 | * | 2363 | * |
| 2358 | * Return value is the same as kernfs_path(). | 2364 | * Return value is the same as kernfs_path(). |
| 2359 | */ | 2365 | */ |
| 2360 | char *task_cgroup_path(struct task_struct *task, char *buf, size_t buflen) | 2366 | int task_cgroup_path(struct task_struct *task, char *buf, size_t buflen) |
| 2361 | { | 2367 | { |
| 2362 | struct cgroup_root *root; | 2368 | struct cgroup_root *root; |
| 2363 | struct cgroup *cgrp; | 2369 | struct cgroup *cgrp; |
| 2364 | int hierarchy_id = 1; | 2370 | int hierarchy_id = 1; |
| 2365 | char *path = NULL; | 2371 | int ret; |
| 2366 | 2372 | ||
| 2367 | mutex_lock(&cgroup_mutex); | 2373 | mutex_lock(&cgroup_mutex); |
| 2368 | spin_lock_irq(&css_set_lock); | 2374 | spin_lock_irq(&css_set_lock); |
| @@ -2371,16 +2377,15 @@ char *task_cgroup_path(struct task_struct *task, char *buf, size_t buflen) | |||
| 2371 | 2377 | ||
| 2372 | if (root) { | 2378 | if (root) { |
| 2373 | cgrp = task_cgroup_from_root(task, root); | 2379 | cgrp = task_cgroup_from_root(task, root); |
| 2374 | path = cgroup_path_ns_locked(cgrp, buf, buflen, &init_cgroup_ns); | 2380 | ret = cgroup_path_ns_locked(cgrp, buf, buflen, &init_cgroup_ns); |
| 2375 | } else { | 2381 | } else { |
| 2376 | /* if no hierarchy exists, everyone is in "/" */ | 2382 | /* if no hierarchy exists, everyone is in "/" */ |
| 2377 | if (strlcpy(buf, "/", buflen) < buflen) | 2383 | ret = strlcpy(buf, "/", buflen); |
| 2378 | path = buf; | ||
| 2379 | } | 2384 | } |
| 2380 | 2385 | ||
| 2381 | spin_unlock_irq(&css_set_lock); | 2386 | spin_unlock_irq(&css_set_lock); |
| 2382 | mutex_unlock(&cgroup_mutex); | 2387 | mutex_unlock(&cgroup_mutex); |
| 2383 | return path; | 2388 | return ret; |
| 2384 | } | 2389 | } |
| 2385 | EXPORT_SYMBOL_GPL(task_cgroup_path); | 2390 | EXPORT_SYMBOL_GPL(task_cgroup_path); |
| 2386 | 2391 | ||
| @@ -2830,6 +2835,10 @@ static int cgroup_attach_task(struct cgroup *dst_cgrp, | |||
| 2830 | ret = cgroup_migrate(leader, threadgroup, dst_cgrp->root); | 2835 | ret = cgroup_migrate(leader, threadgroup, dst_cgrp->root); |
| 2831 | 2836 | ||
| 2832 | cgroup_migrate_finish(&preloaded_csets); | 2837 | cgroup_migrate_finish(&preloaded_csets); |
| 2838 | |||
| 2839 | if (!ret) | ||
| 2840 | trace_cgroup_attach_task(dst_cgrp, leader, threadgroup); | ||
| 2841 | |||
| 2833 | return ret; | 2842 | return ret; |
| 2834 | } | 2843 | } |
| 2835 | 2844 | ||
| @@ -3611,6 +3620,8 @@ static int cgroup_rename(struct kernfs_node *kn, struct kernfs_node *new_parent, | |||
| 3611 | mutex_lock(&cgroup_mutex); | 3620 | mutex_lock(&cgroup_mutex); |
| 3612 | 3621 | ||
| 3613 | ret = kernfs_rename(kn, new_parent, new_name_str); | 3622 | ret = kernfs_rename(kn, new_parent, new_name_str); |
| 3623 | if (!ret) | ||
| 3624 | trace_cgroup_rename(cgrp); | ||
| 3614 | 3625 | ||
| 3615 | mutex_unlock(&cgroup_mutex); | 3626 | mutex_unlock(&cgroup_mutex); |
| 3616 | 3627 | ||
| @@ -4381,6 +4392,8 @@ int cgroup_transfer_tasks(struct cgroup *to, struct cgroup *from) | |||
| 4381 | 4392 | ||
| 4382 | if (task) { | 4393 | if (task) { |
| 4383 | ret = cgroup_migrate(task, false, to->root); | 4394 | ret = cgroup_migrate(task, false, to->root); |
| 4395 | if (!ret) | ||
| 4396 | trace_cgroup_transfer_tasks(to, task, false); | ||
| 4384 | put_task_struct(task); | 4397 | put_task_struct(task); |
| 4385 | } | 4398 | } |
| 4386 | } while (task && !ret); | 4399 | } while (task && !ret); |
| @@ -5046,6 +5059,8 @@ static void css_release_work_fn(struct work_struct *work) | |||
| 5046 | ss->css_released(css); | 5059 | ss->css_released(css); |
| 5047 | } else { | 5060 | } else { |
| 5048 | /* cgroup release path */ | 5061 | /* cgroup release path */ |
| 5062 | trace_cgroup_release(cgrp); | ||
| 5063 | |||
| 5049 | cgroup_idr_remove(&cgrp->root->cgroup_idr, cgrp->id); | 5064 | cgroup_idr_remove(&cgrp->root->cgroup_idr, cgrp->id); |
| 5050 | cgrp->id = -1; | 5065 | cgrp->id = -1; |
| 5051 | 5066 | ||
| @@ -5332,6 +5347,8 @@ static int cgroup_mkdir(struct kernfs_node *parent_kn, const char *name, | |||
| 5332 | if (ret) | 5347 | if (ret) |
| 5333 | goto out_destroy; | 5348 | goto out_destroy; |
| 5334 | 5349 | ||
| 5350 | trace_cgroup_mkdir(cgrp); | ||
| 5351 | |||
| 5335 | /* let's create and online css's */ | 5352 | /* let's create and online css's */ |
| 5336 | kernfs_activate(kn); | 5353 | kernfs_activate(kn); |
| 5337 | 5354 | ||
| @@ -5507,6 +5524,9 @@ static int cgroup_rmdir(struct kernfs_node *kn) | |||
| 5507 | 5524 | ||
| 5508 | ret = cgroup_destroy_locked(cgrp); | 5525 | ret = cgroup_destroy_locked(cgrp); |
| 5509 | 5526 | ||
| 5527 | if (!ret) | ||
| 5528 | trace_cgroup_rmdir(cgrp); | ||
| 5529 | |||
| 5510 | cgroup_kn_unlock(kn); | 5530 | cgroup_kn_unlock(kn); |
| 5511 | return ret; | 5531 | return ret; |
| 5512 | } | 5532 | } |
| @@ -5743,7 +5763,7 @@ core_initcall(cgroup_wq_init); | |||
| 5743 | int proc_cgroup_show(struct seq_file *m, struct pid_namespace *ns, | 5763 | int proc_cgroup_show(struct seq_file *m, struct pid_namespace *ns, |
| 5744 | struct pid *pid, struct task_struct *tsk) | 5764 | struct pid *pid, struct task_struct *tsk) |
| 5745 | { | 5765 | { |
| 5746 | char *buf, *path; | 5766 | char *buf; |
| 5747 | int retval; | 5767 | int retval; |
| 5748 | struct cgroup_root *root; | 5768 | struct cgroup_root *root; |
| 5749 | 5769 | ||
| @@ -5786,18 +5806,18 @@ int proc_cgroup_show(struct seq_file *m, struct pid_namespace *ns, | |||
| 5786 | * " (deleted)" is appended to the cgroup path. | 5806 | * " (deleted)" is appended to the cgroup path. |
| 5787 | */ | 5807 | */ |
| 5788 | if (cgroup_on_dfl(cgrp) || !(tsk->flags & PF_EXITING)) { | 5808 | if (cgroup_on_dfl(cgrp) || !(tsk->flags & PF_EXITING)) { |
| 5789 | path = cgroup_path_ns_locked(cgrp, buf, PATH_MAX, | 5809 | retval = cgroup_path_ns_locked(cgrp, buf, PATH_MAX, |
| 5790 | current->nsproxy->cgroup_ns); | 5810 | current->nsproxy->cgroup_ns); |
| 5791 | if (!path) { | 5811 | if (retval >= PATH_MAX) |
| 5792 | retval = -ENAMETOOLONG; | 5812 | retval = -ENAMETOOLONG; |
| 5813 | if (retval < 0) | ||
| 5793 | goto out_unlock; | 5814 | goto out_unlock; |
| 5794 | } | 5815 | |
| 5816 | seq_puts(m, buf); | ||
| 5795 | } else { | 5817 | } else { |
| 5796 | path = "/"; | 5818 | seq_puts(m, "/"); |
| 5797 | } | 5819 | } |
| 5798 | 5820 | ||
| 5799 | seq_puts(m, path); | ||
| 5800 | |||
| 5801 | if (cgroup_on_dfl(cgrp) && cgroup_is_dead(cgrp)) | 5821 | if (cgroup_on_dfl(cgrp) && cgroup_is_dead(cgrp)) |
| 5802 | seq_puts(m, " (deleted)\n"); | 5822 | seq_puts(m, " (deleted)\n"); |
| 5803 | else | 5823 | else |
| @@ -6062,8 +6082,9 @@ static void cgroup_release_agent(struct work_struct *work) | |||
| 6062 | { | 6082 | { |
| 6063 | struct cgroup *cgrp = | 6083 | struct cgroup *cgrp = |
| 6064 | container_of(work, struct cgroup, release_agent_work); | 6084 | container_of(work, struct cgroup, release_agent_work); |
| 6065 | char *pathbuf = NULL, *agentbuf = NULL, *path; | 6085 | char *pathbuf = NULL, *agentbuf = NULL; |
| 6066 | char *argv[3], *envp[3]; | 6086 | char *argv[3], *envp[3]; |
| 6087 | int ret; | ||
| 6067 | 6088 | ||
| 6068 | mutex_lock(&cgroup_mutex); | 6089 | mutex_lock(&cgroup_mutex); |
| 6069 | 6090 | ||
| @@ -6073,13 +6094,13 @@ static void cgroup_release_agent(struct work_struct *work) | |||
| 6073 | goto out; | 6094 | goto out; |
| 6074 | 6095 | ||
| 6075 | spin_lock_irq(&css_set_lock); | 6096 | spin_lock_irq(&css_set_lock); |
| 6076 | path = cgroup_path_ns_locked(cgrp, pathbuf, PATH_MAX, &init_cgroup_ns); | 6097 | ret = cgroup_path_ns_locked(cgrp, pathbuf, PATH_MAX, &init_cgroup_ns); |
| 6077 | spin_unlock_irq(&css_set_lock); | 6098 | spin_unlock_irq(&css_set_lock); |
| 6078 | if (!path) | 6099 | if (ret < 0 || ret >= PATH_MAX) |
| 6079 | goto out; | 6100 | goto out; |
| 6080 | 6101 | ||
| 6081 | argv[0] = agentbuf; | 6102 | argv[0] = agentbuf; |
| 6082 | argv[1] = path; | 6103 | argv[1] = pathbuf; |
| 6083 | argv[2] = NULL; | 6104 | argv[2] = NULL; |
| 6084 | 6105 | ||
| 6085 | /* minimal command environment */ | 6106 | /* minimal command environment */ |
diff --git a/kernel/cpuset.c b/kernel/cpuset.c index 2b4c20ab5bbe..29f815d2ef7e 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c | |||
| @@ -2715,7 +2715,7 @@ void __cpuset_memory_pressure_bump(void) | |||
| 2715 | int proc_cpuset_show(struct seq_file *m, struct pid_namespace *ns, | 2715 | int proc_cpuset_show(struct seq_file *m, struct pid_namespace *ns, |
| 2716 | struct pid *pid, struct task_struct *tsk) | 2716 | struct pid *pid, struct task_struct *tsk) |
| 2717 | { | 2717 | { |
| 2718 | char *buf, *p; | 2718 | char *buf; |
| 2719 | struct cgroup_subsys_state *css; | 2719 | struct cgroup_subsys_state *css; |
| 2720 | int retval; | 2720 | int retval; |
| 2721 | 2721 | ||
| @@ -2724,14 +2724,15 @@ int proc_cpuset_show(struct seq_file *m, struct pid_namespace *ns, | |||
| 2724 | if (!buf) | 2724 | if (!buf) |
| 2725 | goto out; | 2725 | goto out; |
| 2726 | 2726 | ||
| 2727 | retval = -ENAMETOOLONG; | ||
| 2728 | css = task_get_css(tsk, cpuset_cgrp_id); | 2727 | css = task_get_css(tsk, cpuset_cgrp_id); |
| 2729 | p = cgroup_path_ns(css->cgroup, buf, PATH_MAX, | 2728 | retval = cgroup_path_ns(css->cgroup, buf, PATH_MAX, |
| 2730 | current->nsproxy->cgroup_ns); | 2729 | current->nsproxy->cgroup_ns); |
| 2731 | css_put(css); | 2730 | css_put(css); |
| 2732 | if (!p) | 2731 | if (retval >= PATH_MAX) |
| 2732 | retval = -ENAMETOOLONG; | ||
| 2733 | if (retval < 0) | ||
| 2733 | goto out_free; | 2734 | goto out_free; |
| 2734 | seq_puts(m, p); | 2735 | seq_puts(m, buf); |
| 2735 | seq_putc(m, '\n'); | 2736 | seq_putc(m, '\n'); |
| 2736 | retval = 0; | 2737 | retval = 0; |
| 2737 | out_free: | 2738 | out_free: |
diff --git a/kernel/sched/debug.c b/kernel/sched/debug.c index 13935886a471..fa178b62ea79 100644 --- a/kernel/sched/debug.c +++ b/kernel/sched/debug.c | |||
| @@ -415,7 +415,8 @@ static char *task_group_path(struct task_group *tg) | |||
| 415 | if (autogroup_path(tg, group_path, PATH_MAX)) | 415 | if (autogroup_path(tg, group_path, PATH_MAX)) |
| 416 | return group_path; | 416 | return group_path; |
| 417 | 417 | ||
| 418 | return cgroup_path(tg->css.cgroup, group_path, PATH_MAX); | 418 | cgroup_path(tg->css.cgroup, group_path, PATH_MAX); |
| 419 | return group_path; | ||
| 419 | } | 420 | } |
| 420 | #endif | 421 | #endif |
| 421 | 422 | ||
