diff options
Diffstat (limited to 'kernel/cgroup.c')
-rw-r--r-- | kernel/cgroup.c | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 909a7d31ffd3..86cb5c6e8932 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c | |||
@@ -1215,6 +1215,41 @@ static void cgroup_destroy_root(struct cgroup_root *root) | |||
1215 | cgroup_free_root(root); | 1215 | cgroup_free_root(root); |
1216 | } | 1216 | } |
1217 | 1217 | ||
1218 | /* | ||
1219 | * look up cgroup associated with current task's cgroup namespace on the | ||
1220 | * specified hierarchy | ||
1221 | */ | ||
1222 | static struct cgroup * | ||
1223 | current_cgns_cgroup_from_root(struct cgroup_root *root) | ||
1224 | { | ||
1225 | struct cgroup *res = NULL; | ||
1226 | struct css_set *cset; | ||
1227 | |||
1228 | lockdep_assert_held(&css_set_lock); | ||
1229 | |||
1230 | rcu_read_lock(); | ||
1231 | |||
1232 | cset = current->nsproxy->cgroup_ns->root_cset; | ||
1233 | if (cset == &init_css_set) { | ||
1234 | res = &root->cgrp; | ||
1235 | } else { | ||
1236 | struct cgrp_cset_link *link; | ||
1237 | |||
1238 | list_for_each_entry(link, &cset->cgrp_links, cgrp_link) { | ||
1239 | struct cgroup *c = link->cgrp; | ||
1240 | |||
1241 | if (c->root == root) { | ||
1242 | res = c; | ||
1243 | break; | ||
1244 | } | ||
1245 | } | ||
1246 | } | ||
1247 | rcu_read_unlock(); | ||
1248 | |||
1249 | BUG_ON(!res); | ||
1250 | return res; | ||
1251 | } | ||
1252 | |||
1218 | /* look up cgroup associated with given css_set on the specified hierarchy */ | 1253 | /* look up cgroup associated with given css_set on the specified hierarchy */ |
1219 | static struct cgroup *cset_cgroup_from_root(struct css_set *cset, | 1254 | static struct cgroup *cset_cgroup_from_root(struct css_set *cset, |
1220 | struct cgroup_root *root) | 1255 | struct cgroup_root *root) |
@@ -1593,6 +1628,33 @@ static int rebind_subsystems(struct cgroup_root *dst_root, u16 ss_mask) | |||
1593 | return 0; | 1628 | return 0; |
1594 | } | 1629 | } |
1595 | 1630 | ||
1631 | static int cgroup_show_path(struct seq_file *sf, struct kernfs_node *kf_node, | ||
1632 | struct kernfs_root *kf_root) | ||
1633 | { | ||
1634 | int len = 0; | ||
1635 | char *buf = NULL; | ||
1636 | struct cgroup_root *kf_cgroot = cgroup_root_from_kf(kf_root); | ||
1637 | struct cgroup *ns_cgroup; | ||
1638 | |||
1639 | buf = kmalloc(PATH_MAX, GFP_KERNEL); | ||
1640 | if (!buf) | ||
1641 | return -ENOMEM; | ||
1642 | |||
1643 | spin_lock_bh(&css_set_lock); | ||
1644 | ns_cgroup = current_cgns_cgroup_from_root(kf_cgroot); | ||
1645 | len = kernfs_path_from_node(kf_node, ns_cgroup->kn, buf, PATH_MAX); | ||
1646 | spin_unlock_bh(&css_set_lock); | ||
1647 | |||
1648 | if (len >= PATH_MAX) | ||
1649 | len = -ERANGE; | ||
1650 | else if (len > 0) { | ||
1651 | seq_escape(sf, buf, " \t\n\\"); | ||
1652 | len = 0; | ||
1653 | } | ||
1654 | kfree(buf); | ||
1655 | return len; | ||
1656 | } | ||
1657 | |||
1596 | static int cgroup_show_options(struct seq_file *seq, | 1658 | static int cgroup_show_options(struct seq_file *seq, |
1597 | struct kernfs_root *kf_root) | 1659 | struct kernfs_root *kf_root) |
1598 | { | 1660 | { |
@@ -5433,6 +5495,7 @@ static struct kernfs_syscall_ops cgroup_kf_syscall_ops = { | |||
5433 | .mkdir = cgroup_mkdir, | 5495 | .mkdir = cgroup_mkdir, |
5434 | .rmdir = cgroup_rmdir, | 5496 | .rmdir = cgroup_rmdir, |
5435 | .rename = cgroup_rename, | 5497 | .rename = cgroup_rename, |
5498 | .show_path = cgroup_show_path, | ||
5436 | }; | 5499 | }; |
5437 | 5500 | ||
5438 | static void __init cgroup_init_subsys(struct cgroup_subsys *ss, bool early) | 5501 | static void __init cgroup_init_subsys(struct cgroup_subsys *ss, bool early) |