diff options
-rw-r--r-- | kernel/cgroup.c | 47 |
1 files changed, 33 insertions, 14 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 7dc8788cfd52..940aced4ed00 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 | ||
@@ -4387,6 +4402,15 @@ static void css_release_work_fn(struct work_struct *work) | |||
4387 | /* cgroup release path */ | 4402 | /* cgroup release path */ |
4388 | cgroup_idr_remove(&cgrp->root->cgroup_idr, cgrp->id); | 4403 | cgroup_idr_remove(&cgrp->root->cgroup_idr, cgrp->id); |
4389 | cgrp->id = -1; | 4404 | cgrp->id = -1; |
4405 | |||
4406 | /* | ||
4407 | * There are two control paths which try to determine | ||
4408 | * cgroup from dentry without going through kernfs - | ||
4409 | * cgroupstats_build() and css_tryget_online_from_dir(). | ||
4410 | * Those are supported by RCU protecting clearing of | ||
4411 | * cgrp->kn->priv backpointer. | ||
4412 | */ | ||
4413 | RCU_INIT_POINTER(*(void __rcu __force **)&cgrp->kn->priv, NULL); | ||
4390 | } | 4414 | } |
4391 | 4415 | ||
4392 | mutex_unlock(&cgroup_mutex); | 4416 | mutex_unlock(&cgroup_mutex); |
@@ -4543,6 +4567,11 @@ static int cgroup_mkdir(struct kernfs_node *parent_kn, const char *name, | |||
4543 | struct cftype *base_files; | 4567 | struct cftype *base_files; |
4544 | int ssid, ret; | 4568 | int ssid, ret; |
4545 | 4569 | ||
4570 | /* Do not accept '\n' to prevent making /proc/<pid>/cgroup unparsable. | ||
4571 | */ | ||
4572 | if (strchr(name, '\n')) | ||
4573 | return -EINVAL; | ||
4574 | |||
4546 | parent = cgroup_kn_lock_live(parent_kn); | 4575 | parent = cgroup_kn_lock_live(parent_kn); |
4547 | if (!parent) | 4576 | if (!parent) |
4548 | return -ENODEV; | 4577 | return -ENODEV; |
@@ -4820,16 +4849,6 @@ static int cgroup_rmdir(struct kernfs_node *kn) | |||
4820 | 4849 | ||
4821 | cgroup_kn_unlock(kn); | 4850 | cgroup_kn_unlock(kn); |
4822 | 4851 | ||
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); | 4852 | cgroup_put(cgrp); |
4834 | return ret; | 4853 | return ret; |
4835 | } | 4854 | } |
@@ -5416,7 +5435,7 @@ struct cgroup_subsys_state *css_tryget_online_from_dir(struct dentry *dentry, | |||
5416 | /* | 5435 | /* |
5417 | * This path doesn't originate from kernfs and @kn could already | 5436 | * This path doesn't originate from kernfs and @kn could already |
5418 | * have been or be removed at any point. @kn->priv is RCU | 5437 | * have been or be removed at any point. @kn->priv is RCU |
5419 | * protected for this access. See cgroup_rmdir() for details. | 5438 | * protected for this access. See css_release_work_fn() for details. |
5420 | */ | 5439 | */ |
5421 | cgrp = rcu_dereference(kn->priv); | 5440 | cgrp = rcu_dereference(kn->priv); |
5422 | if (cgrp) | 5441 | if (cgrp) |