diff options
Diffstat (limited to 'kernel/cgroup.c')
-rw-r--r-- | kernel/cgroup.c | 146 |
1 files changed, 33 insertions, 113 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 59dfb025f1ac..638df032fb94 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c | |||
@@ -145,8 +145,6 @@ static int cgroup_root_count; | |||
145 | /* hierarchy ID allocation and mapping, protected by cgroup_mutex */ | 145 | /* hierarchy ID allocation and mapping, protected by cgroup_mutex */ |
146 | static DEFINE_IDR(cgroup_hierarchy_idr); | 146 | static DEFINE_IDR(cgroup_hierarchy_idr); |
147 | 147 | ||
148 | static struct cgroup_name root_cgroup_name = { .name = "/" }; | ||
149 | |||
150 | /* | 148 | /* |
151 | * Assign a monotonically increasing serial number to cgroups. It | 149 | * Assign a monotonically increasing serial number to cgroups. It |
152 | * guarantees cgroups with bigger numbers are newer than those with smaller | 150 | * guarantees cgroups with bigger numbers are newer than those with smaller |
@@ -888,17 +886,6 @@ static int cgroup_populate_dir(struct cgroup *cgrp, unsigned long subsys_mask); | |||
888 | static struct kernfs_syscall_ops cgroup_kf_syscall_ops; | 886 | static struct kernfs_syscall_ops cgroup_kf_syscall_ops; |
889 | static const struct file_operations proc_cgroupstats_operations; | 887 | static const struct file_operations proc_cgroupstats_operations; |
890 | 888 | ||
891 | static struct cgroup_name *cgroup_alloc_name(const char *name_str) | ||
892 | { | ||
893 | struct cgroup_name *name; | ||
894 | |||
895 | name = kmalloc(sizeof(*name) + strlen(name_str) + 1, GFP_KERNEL); | ||
896 | if (!name) | ||
897 | return NULL; | ||
898 | strcpy(name->name, name_str); | ||
899 | return name; | ||
900 | } | ||
901 | |||
902 | static char *cgroup_file_name(struct cgroup *cgrp, const struct cftype *cft, | 889 | static char *cgroup_file_name(struct cgroup *cgrp, const struct cftype *cft, |
903 | char *buf) | 890 | char *buf) |
904 | { | 891 | { |
@@ -958,8 +945,6 @@ static void cgroup_free_fn(struct work_struct *work) | |||
958 | cgroup_pidlist_destroy_all(cgrp); | 945 | cgroup_pidlist_destroy_all(cgrp); |
959 | 946 | ||
960 | kernfs_put(cgrp->kn); | 947 | kernfs_put(cgrp->kn); |
961 | |||
962 | kfree(rcu_dereference_raw(cgrp->name)); | ||
963 | kfree(cgrp); | 948 | kfree(cgrp); |
964 | } | 949 | } |
965 | 950 | ||
@@ -1377,7 +1362,6 @@ static void init_cgroup_root(struct cgroupfs_root *root) | |||
1377 | INIT_LIST_HEAD(&root->root_list); | 1362 | INIT_LIST_HEAD(&root->root_list); |
1378 | root->number_of_cgroups = 1; | 1363 | root->number_of_cgroups = 1; |
1379 | cgrp->root = root; | 1364 | cgrp->root = root; |
1380 | RCU_INIT_POINTER(cgrp->name, &root_cgroup_name); | ||
1381 | init_cgroup_housekeeping(cgrp); | 1365 | init_cgroup_housekeeping(cgrp); |
1382 | idr_init(&root->cgroup_idr); | 1366 | idr_init(&root->cgroup_idr); |
1383 | } | 1367 | } |
@@ -1598,57 +1582,6 @@ static struct file_system_type cgroup_fs_type = { | |||
1598 | static struct kobject *cgroup_kobj; | 1582 | static struct kobject *cgroup_kobj; |
1599 | 1583 | ||
1600 | /** | 1584 | /** |
1601 | * cgroup_path - generate the path of a cgroup | ||
1602 | * @cgrp: the cgroup in question | ||
1603 | * @buf: the buffer to write the path into | ||
1604 | * @buflen: the length of the buffer | ||
1605 | * | ||
1606 | * Writes path of cgroup into buf. Returns 0 on success, -errno on error. | ||
1607 | * | ||
1608 | * We can't generate cgroup path using dentry->d_name, as accessing | ||
1609 | * dentry->name must be protected by irq-unsafe dentry->d_lock or parent | ||
1610 | * inode's i_mutex, while on the other hand cgroup_path() can be called | ||
1611 | * with some irq-safe spinlocks held. | ||
1612 | */ | ||
1613 | int cgroup_path(const struct cgroup *cgrp, char *buf, int buflen) | ||
1614 | { | ||
1615 | int ret = -ENAMETOOLONG; | ||
1616 | char *start; | ||
1617 | |||
1618 | if (!cgrp->parent) { | ||
1619 | if (strlcpy(buf, "/", buflen) >= buflen) | ||
1620 | return -ENAMETOOLONG; | ||
1621 | return 0; | ||
1622 | } | ||
1623 | |||
1624 | start = buf + buflen - 1; | ||
1625 | *start = '\0'; | ||
1626 | |||
1627 | rcu_read_lock(); | ||
1628 | do { | ||
1629 | const char *name = cgroup_name(cgrp); | ||
1630 | int len; | ||
1631 | |||
1632 | len = strlen(name); | ||
1633 | if ((start -= len) < buf) | ||
1634 | goto out; | ||
1635 | memcpy(start, name, len); | ||
1636 | |||
1637 | if (--start < buf) | ||
1638 | goto out; | ||
1639 | *start = '/'; | ||
1640 | |||
1641 | cgrp = cgrp->parent; | ||
1642 | } while (cgrp->parent); | ||
1643 | ret = 0; | ||
1644 | memmove(buf, start, buf + buflen - start); | ||
1645 | out: | ||
1646 | rcu_read_unlock(); | ||
1647 | return ret; | ||
1648 | } | ||
1649 | EXPORT_SYMBOL_GPL(cgroup_path); | ||
1650 | |||
1651 | /** | ||
1652 | * task_cgroup_path - cgroup path of a task in the first cgroup hierarchy | 1585 | * task_cgroup_path - cgroup path of a task in the first cgroup hierarchy |
1653 | * @task: target task | 1586 | * @task: target task |
1654 | * @buf: the buffer to write the path into | 1587 | * @buf: the buffer to write the path into |
@@ -1659,16 +1592,14 @@ EXPORT_SYMBOL_GPL(cgroup_path); | |||
1659 | * function grabs cgroup_mutex and shouldn't be used inside locks used by | 1592 | * function grabs cgroup_mutex and shouldn't be used inside locks used by |
1660 | * cgroup controller callbacks. | 1593 | * cgroup controller callbacks. |
1661 | * | 1594 | * |
1662 | * Returns 0 on success, fails with -%ENAMETOOLONG if @buflen is too short. | 1595 | * Return value is the same as kernfs_path(). |
1663 | */ | 1596 | */ |
1664 | int task_cgroup_path(struct task_struct *task, char *buf, size_t buflen) | 1597 | char *task_cgroup_path(struct task_struct *task, char *buf, size_t buflen) |
1665 | { | 1598 | { |
1666 | struct cgroupfs_root *root; | 1599 | struct cgroupfs_root *root; |
1667 | struct cgroup *cgrp; | 1600 | struct cgroup *cgrp; |
1668 | int hierarchy_id = 1, ret = 0; | 1601 | int hierarchy_id = 1; |
1669 | 1602 | char *path = NULL; | |
1670 | if (buflen < 2) | ||
1671 | return -ENAMETOOLONG; | ||
1672 | 1603 | ||
1673 | mutex_lock(&cgroup_mutex); | 1604 | mutex_lock(&cgroup_mutex); |
1674 | 1605 | ||
@@ -1676,14 +1607,15 @@ int task_cgroup_path(struct task_struct *task, char *buf, size_t buflen) | |||
1676 | 1607 | ||
1677 | if (root) { | 1608 | if (root) { |
1678 | cgrp = task_cgroup_from_root(task, root); | 1609 | cgrp = task_cgroup_from_root(task, root); |
1679 | ret = cgroup_path(cgrp, buf, buflen); | 1610 | path = cgroup_path(cgrp, buf, buflen); |
1680 | } else { | 1611 | } else { |
1681 | /* if no hierarchy exists, everyone is in "/" */ | 1612 | /* if no hierarchy exists, everyone is in "/" */ |
1682 | memcpy(buf, "/", 2); | 1613 | if (strlcpy(buf, "/", buflen) < buflen) |
1614 | path = buf; | ||
1683 | } | 1615 | } |
1684 | 1616 | ||
1685 | mutex_unlock(&cgroup_mutex); | 1617 | mutex_unlock(&cgroup_mutex); |
1686 | return ret; | 1618 | return path; |
1687 | } | 1619 | } |
1688 | EXPORT_SYMBOL_GPL(task_cgroup_path); | 1620 | EXPORT_SYMBOL_GPL(task_cgroup_path); |
1689 | 1621 | ||
@@ -2211,7 +2143,6 @@ static int cgroup_rename(struct kernfs_node *kn, struct kernfs_node *new_parent, | |||
2211 | const char *new_name_str) | 2143 | const char *new_name_str) |
2212 | { | 2144 | { |
2213 | struct cgroup *cgrp = kn->priv; | 2145 | struct cgroup *cgrp = kn->priv; |
2214 | struct cgroup_name *name, *old_name; | ||
2215 | int ret; | 2146 | int ret; |
2216 | 2147 | ||
2217 | if (kernfs_type(kn) != KERNFS_DIR) | 2148 | if (kernfs_type(kn) != KERNFS_DIR) |
@@ -2226,25 +2157,13 @@ static int cgroup_rename(struct kernfs_node *kn, struct kernfs_node *new_parent, | |||
2226 | if (cgroup_sane_behavior(cgrp)) | 2157 | if (cgroup_sane_behavior(cgrp)) |
2227 | return -EPERM; | 2158 | return -EPERM; |
2228 | 2159 | ||
2229 | name = cgroup_alloc_name(new_name_str); | ||
2230 | if (!name) | ||
2231 | return -ENOMEM; | ||
2232 | |||
2233 | mutex_lock(&cgroup_tree_mutex); | 2160 | mutex_lock(&cgroup_tree_mutex); |
2234 | mutex_lock(&cgroup_mutex); | 2161 | mutex_lock(&cgroup_mutex); |
2235 | 2162 | ||
2236 | ret = kernfs_rename(kn, new_parent, new_name_str); | 2163 | ret = kernfs_rename(kn, new_parent, new_name_str); |
2237 | if (!ret) { | ||
2238 | old_name = rcu_dereference_protected(cgrp->name, true); | ||
2239 | rcu_assign_pointer(cgrp->name, name); | ||
2240 | } else { | ||
2241 | old_name = name; | ||
2242 | } | ||
2243 | 2164 | ||
2244 | mutex_unlock(&cgroup_mutex); | 2165 | mutex_unlock(&cgroup_mutex); |
2245 | mutex_unlock(&cgroup_tree_mutex); | 2166 | mutex_unlock(&cgroup_tree_mutex); |
2246 | |||
2247 | kfree_rcu(old_name, rcu_head); | ||
2248 | return ret; | 2167 | return ret; |
2249 | } | 2168 | } |
2250 | 2169 | ||
@@ -3719,14 +3638,13 @@ err_free: | |||
3719 | /** | 3638 | /** |
3720 | * cgroup_create - create a cgroup | 3639 | * cgroup_create - create a cgroup |
3721 | * @parent: cgroup that will be parent of the new cgroup | 3640 | * @parent: cgroup that will be parent of the new cgroup |
3722 | * @name_str: name of the new cgroup | 3641 | * @name: name of the new cgroup |
3723 | * @mode: mode to set on new cgroup | 3642 | * @mode: mode to set on new cgroup |
3724 | */ | 3643 | */ |
3725 | static long cgroup_create(struct cgroup *parent, const char *name_str, | 3644 | static long cgroup_create(struct cgroup *parent, const char *name, |
3726 | umode_t mode) | 3645 | umode_t mode) |
3727 | { | 3646 | { |
3728 | struct cgroup *cgrp; | 3647 | struct cgroup *cgrp; |
3729 | struct cgroup_name *name; | ||
3730 | struct cgroupfs_root *root = parent->root; | 3648 | struct cgroupfs_root *root = parent->root; |
3731 | int ssid, err; | 3649 | int ssid, err; |
3732 | struct cgroup_subsys *ss; | 3650 | struct cgroup_subsys *ss; |
@@ -3737,13 +3655,6 @@ static long cgroup_create(struct cgroup *parent, const char *name_str, | |||
3737 | if (!cgrp) | 3655 | if (!cgrp) |
3738 | return -ENOMEM; | 3656 | return -ENOMEM; |
3739 | 3657 | ||
3740 | name = cgroup_alloc_name(name_str); | ||
3741 | if (!name) { | ||
3742 | err = -ENOMEM; | ||
3743 | goto err_free_cgrp; | ||
3744 | } | ||
3745 | rcu_assign_pointer(cgrp->name, name); | ||
3746 | |||
3747 | mutex_lock(&cgroup_tree_mutex); | 3658 | mutex_lock(&cgroup_tree_mutex); |
3748 | 3659 | ||
3749 | /* | 3660 | /* |
@@ -3781,7 +3692,7 @@ static long cgroup_create(struct cgroup *parent, const char *name_str, | |||
3781 | set_bit(CGRP_CPUSET_CLONE_CHILDREN, &cgrp->flags); | 3692 | set_bit(CGRP_CPUSET_CLONE_CHILDREN, &cgrp->flags); |
3782 | 3693 | ||
3783 | /* create the directory */ | 3694 | /* create the directory */ |
3784 | kn = kernfs_create_dir(parent->kn, name->name, mode, cgrp); | 3695 | kn = kernfs_create_dir(parent->kn, name, mode, cgrp); |
3785 | if (IS_ERR(kn)) { | 3696 | if (IS_ERR(kn)) { |
3786 | err = PTR_ERR(kn); | 3697 | err = PTR_ERR(kn); |
3787 | goto err_free_id; | 3698 | goto err_free_id; |
@@ -3839,8 +3750,6 @@ err_unlock: | |||
3839 | mutex_unlock(&cgroup_mutex); | 3750 | mutex_unlock(&cgroup_mutex); |
3840 | err_unlock_tree: | 3751 | err_unlock_tree: |
3841 | mutex_unlock(&cgroup_tree_mutex); | 3752 | mutex_unlock(&cgroup_tree_mutex); |
3842 | kfree(rcu_dereference_raw(cgrp->name)); | ||
3843 | err_free_cgrp: | ||
3844 | kfree(cgrp); | 3753 | kfree(cgrp); |
3845 | return err; | 3754 | return err; |
3846 | 3755 | ||
@@ -4304,12 +4213,12 @@ int proc_cgroup_show(struct seq_file *m, void *v) | |||
4304 | { | 4213 | { |
4305 | struct pid *pid; | 4214 | struct pid *pid; |
4306 | struct task_struct *tsk; | 4215 | struct task_struct *tsk; |
4307 | char *buf; | 4216 | char *buf, *path; |
4308 | int retval; | 4217 | int retval; |
4309 | struct cgroupfs_root *root; | 4218 | struct cgroupfs_root *root; |
4310 | 4219 | ||
4311 | retval = -ENOMEM; | 4220 | retval = -ENOMEM; |
4312 | buf = kmalloc(PAGE_SIZE, GFP_KERNEL); | 4221 | buf = kmalloc(PATH_MAX, GFP_KERNEL); |
4313 | if (!buf) | 4222 | if (!buf) |
4314 | goto out; | 4223 | goto out; |
4315 | 4224 | ||
@@ -4337,10 +4246,12 @@ int proc_cgroup_show(struct seq_file *m, void *v) | |||
4337 | root->name); | 4246 | root->name); |
4338 | seq_putc(m, ':'); | 4247 | seq_putc(m, ':'); |
4339 | cgrp = task_cgroup_from_root(tsk, root); | 4248 | cgrp = task_cgroup_from_root(tsk, root); |
4340 | retval = cgroup_path(cgrp, buf, PAGE_SIZE); | 4249 | path = cgroup_path(cgrp, buf, PATH_MAX); |
4341 | if (retval < 0) | 4250 | if (!path) { |
4251 | retval = -ENAMETOOLONG; | ||
4342 | goto out_unlock; | 4252 | goto out_unlock; |
4343 | seq_puts(m, buf); | 4253 | } |
4254 | seq_puts(m, path); | ||
4344 | seq_putc(m, '\n'); | 4255 | seq_putc(m, '\n'); |
4345 | } | 4256 | } |
4346 | 4257 | ||
@@ -4588,16 +4499,17 @@ static void cgroup_release_agent(struct work_struct *work) | |||
4588 | while (!list_empty(&release_list)) { | 4499 | while (!list_empty(&release_list)) { |
4589 | char *argv[3], *envp[3]; | 4500 | char *argv[3], *envp[3]; |
4590 | int i; | 4501 | int i; |
4591 | char *pathbuf = NULL, *agentbuf = NULL; | 4502 | char *pathbuf = NULL, *agentbuf = NULL, *path; |
4592 | struct cgroup *cgrp = list_entry(release_list.next, | 4503 | struct cgroup *cgrp = list_entry(release_list.next, |
4593 | struct cgroup, | 4504 | struct cgroup, |
4594 | release_list); | 4505 | release_list); |
4595 | list_del_init(&cgrp->release_list); | 4506 | list_del_init(&cgrp->release_list); |
4596 | raw_spin_unlock(&release_list_lock); | 4507 | raw_spin_unlock(&release_list_lock); |
4597 | pathbuf = kmalloc(PAGE_SIZE, GFP_KERNEL); | 4508 | pathbuf = kmalloc(PATH_MAX, GFP_KERNEL); |
4598 | if (!pathbuf) | 4509 | if (!pathbuf) |
4599 | goto continue_free; | 4510 | goto continue_free; |
4600 | if (cgroup_path(cgrp, pathbuf, PAGE_SIZE) < 0) | 4511 | path = cgroup_path(cgrp, pathbuf, PATH_MAX); |
4512 | if (!path) | ||
4601 | goto continue_free; | 4513 | goto continue_free; |
4602 | agentbuf = kstrdup(cgrp->root->release_agent_path, GFP_KERNEL); | 4514 | agentbuf = kstrdup(cgrp->root->release_agent_path, GFP_KERNEL); |
4603 | if (!agentbuf) | 4515 | if (!agentbuf) |
@@ -4605,7 +4517,7 @@ static void cgroup_release_agent(struct work_struct *work) | |||
4605 | 4517 | ||
4606 | i = 0; | 4518 | i = 0; |
4607 | argv[i++] = agentbuf; | 4519 | argv[i++] = agentbuf; |
4608 | argv[i++] = pathbuf; | 4520 | argv[i++] = path; |
4609 | argv[i] = NULL; | 4521 | argv[i] = NULL; |
4610 | 4522 | ||
4611 | i = 0; | 4523 | i = 0; |
@@ -4755,6 +4667,11 @@ static int current_css_set_cg_links_read(struct seq_file *seq, void *v) | |||
4755 | { | 4667 | { |
4756 | struct cgrp_cset_link *link; | 4668 | struct cgrp_cset_link *link; |
4757 | struct css_set *cset; | 4669 | struct css_set *cset; |
4670 | char *name_buf; | ||
4671 | |||
4672 | name_buf = kmalloc(NAME_MAX + 1, GFP_KERNEL); | ||
4673 | if (!name_buf) | ||
4674 | return -ENOMEM; | ||
4758 | 4675 | ||
4759 | read_lock(&css_set_lock); | 4676 | read_lock(&css_set_lock); |
4760 | rcu_read_lock(); | 4677 | rcu_read_lock(); |
@@ -4763,14 +4680,17 @@ static int current_css_set_cg_links_read(struct seq_file *seq, void *v) | |||
4763 | struct cgroup *c = link->cgrp; | 4680 | struct cgroup *c = link->cgrp; |
4764 | const char *name = "?"; | 4681 | const char *name = "?"; |
4765 | 4682 | ||
4766 | if (c != cgroup_dummy_top) | 4683 | if (c != cgroup_dummy_top) { |
4767 | name = cgroup_name(c); | 4684 | cgroup_name(c, name_buf, NAME_MAX + 1); |
4685 | name = name_buf; | ||
4686 | } | ||
4768 | 4687 | ||
4769 | seq_printf(seq, "Root %d group %s\n", | 4688 | seq_printf(seq, "Root %d group %s\n", |
4770 | c->root->hierarchy_id, name); | 4689 | c->root->hierarchy_id, name); |
4771 | } | 4690 | } |
4772 | rcu_read_unlock(); | 4691 | rcu_read_unlock(); |
4773 | read_unlock(&css_set_lock); | 4692 | read_unlock(&css_set_lock); |
4693 | kfree(name_buf); | ||
4774 | return 0; | 4694 | return 0; |
4775 | } | 4695 | } |
4776 | 4696 | ||