diff options
Diffstat (limited to 'kernel/cgroup.c')
-rw-r--r-- | kernel/cgroup.c | 48 |
1 files changed, 33 insertions, 15 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 7dc8788cfd52..3a73f995a81e 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c | |||
@@ -1035,6 +1035,11 @@ static void cgroup_get(struct cgroup *cgrp) | |||
1035 | css_get(&cgrp->self); | 1035 | css_get(&cgrp->self); |
1036 | } | 1036 | } |
1037 | 1037 | ||
1038 | static bool cgroup_tryget(struct cgroup *cgrp) | ||
1039 | { | ||
1040 | return css_tryget(&cgrp->self); | ||
1041 | } | ||
1042 | |||
1038 | static void cgroup_put(struct cgroup *cgrp) | 1043 | static void cgroup_put(struct cgroup *cgrp) |
1039 | { | 1044 | { |
1040 | css_put(&cgrp->self); | 1045 | css_put(&cgrp->self); |
@@ -1147,7 +1152,8 @@ static struct cgroup *cgroup_kn_lock_live(struct kernfs_node *kn) | |||
1147 | * protection against removal. Ensure @cgrp stays accessible and | 1152 | * protection against removal. Ensure @cgrp stays accessible and |
1148 | * break the active_ref protection. | 1153 | * break the active_ref protection. |
1149 | */ | 1154 | */ |
1150 | cgroup_get(cgrp); | 1155 | if (!cgroup_tryget(cgrp)) |
1156 | return NULL; | ||
1151 | kernfs_break_active_protection(kn); | 1157 | kernfs_break_active_protection(kn); |
1152 | 1158 | ||
1153 | mutex_lock(&cgroup_mutex); | 1159 | mutex_lock(&cgroup_mutex); |
@@ -3271,8 +3277,17 @@ int cgroup_add_legacy_cftypes(struct cgroup_subsys *ss, struct cftype *cfts) | |||
3271 | { | 3277 | { |
3272 | struct cftype *cft; | 3278 | struct cftype *cft; |
3273 | 3279 | ||
3274 | for (cft = cfts; cft && cft->name[0] != '\0'; cft++) | 3280 | /* |
3275 | cft->flags |= __CFTYPE_NOT_ON_DFL; | 3281 | * If legacy_flies_on_dfl, we want to show the legacy files on the |
3282 | * dfl hierarchy but iff the target subsystem hasn't been updated | ||
3283 | * for the dfl hierarchy yet. | ||
3284 | */ | ||
3285 | if (!cgroup_legacy_files_on_dfl || | ||
3286 | ss->dfl_cftypes != ss->legacy_cftypes) { | ||
3287 | for (cft = cfts; cft && cft->name[0] != '\0'; cft++) | ||
3288 | cft->flags |= __CFTYPE_NOT_ON_DFL; | ||
3289 | } | ||
3290 | |||
3276 | return cgroup_add_cftypes(ss, cfts); | 3291 | return cgroup_add_cftypes(ss, cfts); |
3277 | } | 3292 | } |
3278 | 3293 | ||
@@ -3970,7 +3985,6 @@ static int pidlist_array_load(struct cgroup *cgrp, enum cgroup_filetype type, | |||
3970 | 3985 | ||
3971 | l = cgroup_pidlist_find_create(cgrp, type); | 3986 | l = cgroup_pidlist_find_create(cgrp, type); |
3972 | if (!l) { | 3987 | if (!l) { |
3973 | mutex_unlock(&cgrp->pidlist_mutex); | ||
3974 | pidlist_free(array); | 3988 | pidlist_free(array); |
3975 | return -ENOMEM; | 3989 | return -ENOMEM; |
3976 | } | 3990 | } |
@@ -4387,6 +4401,15 @@ static void css_release_work_fn(struct work_struct *work) | |||
4387 | /* cgroup release path */ | 4401 | /* cgroup release path */ |
4388 | cgroup_idr_remove(&cgrp->root->cgroup_idr, cgrp->id); | 4402 | cgroup_idr_remove(&cgrp->root->cgroup_idr, cgrp->id); |
4389 | cgrp->id = -1; | 4403 | cgrp->id = -1; |
4404 | |||
4405 | /* | ||
4406 | * There are two control paths which try to determine | ||
4407 | * cgroup from dentry without going through kernfs - | ||
4408 | * cgroupstats_build() and css_tryget_online_from_dir(). | ||
4409 | * Those are supported by RCU protecting clearing of | ||
4410 | * cgrp->kn->priv backpointer. | ||
4411 | */ | ||
4412 | RCU_INIT_POINTER(*(void __rcu __force **)&cgrp->kn->priv, NULL); | ||
4390 | } | 4413 | } |
4391 | 4414 | ||
4392 | mutex_unlock(&cgroup_mutex); | 4415 | mutex_unlock(&cgroup_mutex); |
@@ -4543,6 +4566,11 @@ static int cgroup_mkdir(struct kernfs_node *parent_kn, const char *name, | |||
4543 | struct cftype *base_files; | 4566 | struct cftype *base_files; |
4544 | int ssid, ret; | 4567 | int ssid, ret; |
4545 | 4568 | ||
4569 | /* Do not accept '\n' to prevent making /proc/<pid>/cgroup unparsable. | ||
4570 | */ | ||
4571 | if (strchr(name, '\n')) | ||
4572 | return -EINVAL; | ||
4573 | |||
4546 | parent = cgroup_kn_lock_live(parent_kn); | 4574 | parent = cgroup_kn_lock_live(parent_kn); |
4547 | if (!parent) | 4575 | if (!parent) |
4548 | return -ENODEV; | 4576 | return -ENODEV; |
@@ -4820,16 +4848,6 @@ static int cgroup_rmdir(struct kernfs_node *kn) | |||
4820 | 4848 | ||
4821 | cgroup_kn_unlock(kn); | 4849 | cgroup_kn_unlock(kn); |
4822 | 4850 | ||
4823 | /* | ||
4824 | * There are two control paths which try to determine cgroup from | ||
4825 | * dentry without going through kernfs - cgroupstats_build() and | ||
4826 | * css_tryget_online_from_dir(). Those are supported by RCU | ||
4827 | * protecting clearing of cgrp->kn->priv backpointer, which should | ||
4828 | * happen after all files under it have been removed. | ||
4829 | */ | ||
4830 | if (!ret) | ||
4831 | RCU_INIT_POINTER(*(void __rcu __force **)&kn->priv, NULL); | ||
4832 | |||
4833 | cgroup_put(cgrp); | 4851 | cgroup_put(cgrp); |
4834 | return ret; | 4852 | return ret; |
4835 | } | 4853 | } |
@@ -5416,7 +5434,7 @@ struct cgroup_subsys_state *css_tryget_online_from_dir(struct dentry *dentry, | |||
5416 | /* | 5434 | /* |
5417 | * This path doesn't originate from kernfs and @kn could already | 5435 | * This path doesn't originate from kernfs and @kn could already |
5418 | * have been or be removed at any point. @kn->priv is RCU | 5436 | * have been or be removed at any point. @kn->priv is RCU |
5419 | * protected for this access. See cgroup_rmdir() for details. | 5437 | * protected for this access. See css_release_work_fn() for details. |
5420 | */ | 5438 | */ |
5421 | cgrp = rcu_dereference(kn->priv); | 5439 | cgrp = rcu_dereference(kn->priv); |
5422 | if (cgrp) | 5440 | if (cgrp) |