aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2014-02-12 09:29:48 -0500
committerTejun Heo <tj@kernel.org>2014-02-12 09:29:48 -0500
commit0adb070426dde2fd0b84e7f4f5cefcd8f0b24410 (patch)
treed6acf3d7e39fa838998af178ef340f1d159d2fb2
parent80b13586997d8e584caa772bd99e2a3e55ac6abe (diff)
cgroup: remove cftype_set
cftype_set was added primarily to allow registering the same cftype array more than once for different subsystems. Nobody uses or needs such thing and it's already broken because each cftype has ->ss pointer which is initialized during registration. Let's add list_head ->node to cftype and use the first cftype entry in the array to link them instead of allocating separate cftype_set. While at it, trigger WARN if cft seems previously initialized during registration. This simplifies cftype handling a bit. Signed-off-by: Tejun Heo <tj@kernel.org> Acked-by: Li Zefan <lizefan@huawei.com>
-rw-r--r--include/linux/cgroup.h26
-rw-r--r--kernel/cgroup.c41
2 files changed, 22 insertions, 45 deletions
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
index 305e94ee17f5..b42251a23129 100644
--- a/include/linux/cgroup.h
+++ b/include/linux/cgroup.h
@@ -412,12 +412,11 @@ struct cftype {
412 unsigned int flags; 412 unsigned int flags;
413 413
414 /* 414 /*
415 * The subsys this file belongs to. Initialized automatically 415 * Fields used for internal bookkeeping. Initialized automatically
416 * during registration. NULL for cgroup core files. 416 * during registration.
417 */ 417 */
418 struct cgroup_subsys *ss; 418 struct cgroup_subsys *ss; /* NULL for cgroup core files */
419 419 struct list_head node; /* anchored at ss->cfts */
420 /* kernfs_ops to use, initialized automatically during registration */
421 struct kernfs_ops *kf_ops; 420 struct kernfs_ops *kf_ops;
422 421
423 /* 422 /*
@@ -472,16 +471,6 @@ struct cftype {
472}; 471};
473 472
474/* 473/*
475 * cftype_sets describe cftypes belonging to a subsystem and are chained at
476 * cgroup_subsys->cftsets. Each cftset points to an array of cftypes
477 * terminated by zero length name.
478 */
479struct cftype_set {
480 struct list_head node; /* chained at subsys->cftsets */
481 struct cftype *cfts;
482};
483
484/*
485 * See the comment above CGRP_ROOT_SANE_BEHAVIOR for details. This 474 * See the comment above CGRP_ROOT_SANE_BEHAVIOR for details. This
486 * function can be called as long as @cgrp is accessible. 475 * function can be called as long as @cgrp is accessible.
487 */ 476 */
@@ -597,8 +586,11 @@ struct cgroup_subsys {
597 /* link to parent, protected by cgroup_lock() */ 586 /* link to parent, protected by cgroup_lock() */
598 struct cgroupfs_root *root; 587 struct cgroupfs_root *root;
599 588
600 /* list of cftype_sets */ 589 /*
601 struct list_head cftsets; 590 * List of cftypes. Each entry is the first entry of an array
591 * terminated by zero length name.
592 */
593 struct list_head cfts;
602 594
603 /* base cftypes, automatically registered with subsys itself */ 595 /* base cftypes, automatically registered with subsys itself */
604 struct cftype *base_cftypes; 596 struct cftype *base_cftypes;
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index a2cbd1549995..506ebd61d1c2 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -1016,12 +1016,12 @@ static void cgroup_clear_dir(struct cgroup *cgrp, unsigned long subsys_mask)
1016 int i; 1016 int i;
1017 1017
1018 for_each_subsys(ss, i) { 1018 for_each_subsys(ss, i) {
1019 struct cftype_set *set; 1019 struct cftype *cfts;
1020 1020
1021 if (!test_bit(i, &subsys_mask)) 1021 if (!test_bit(i, &subsys_mask))
1022 continue; 1022 continue;
1023 list_for_each_entry(set, &ss->cftsets, node) 1023 list_for_each_entry(cfts, &ss->cfts, node)
1024 cgroup_addrm_files(cgrp, set->cfts, false); 1024 cgroup_addrm_files(cgrp, cfts, false);
1025 } 1025 }
1026} 1026}
1027 1027
@@ -2392,6 +2392,8 @@ static int cgroup_init_cftypes(struct cgroup_subsys *ss, struct cftype *cfts)
2392 for (cft = cfts; cft->name[0] != '\0'; cft++) { 2392 for (cft = cfts; cft->name[0] != '\0'; cft++) {
2393 struct kernfs_ops *kf_ops; 2393 struct kernfs_ops *kf_ops;
2394 2394
2395 WARN_ON(cft->ss || cft->kf_ops);
2396
2395 if (cft->seq_start) 2397 if (cft->seq_start)
2396 kf_ops = &cgroup_kf_ops; 2398 kf_ops = &cgroup_kf_ops;
2397 else 2399 else
@@ -2430,26 +2432,15 @@ static int cgroup_init_cftypes(struct cgroup_subsys *ss, struct cftype *cfts)
2430 */ 2432 */
2431int cgroup_rm_cftypes(struct cftype *cfts) 2433int cgroup_rm_cftypes(struct cftype *cfts)
2432{ 2434{
2433 struct cftype *found = NULL;
2434 struct cftype_set *set;
2435
2436 if (!cfts || !cfts[0].ss) 2435 if (!cfts || !cfts[0].ss)
2437 return -ENOENT; 2436 return -ENOENT;
2438 2437
2439 cgroup_cfts_prepare(); 2438 cgroup_cfts_prepare();
2439 list_del(&cfts->node);
2440 cgroup_cfts_commit(cfts, false);
2440 2441
2441 list_for_each_entry(set, &cfts[0].ss->cftsets, node) {
2442 if (set->cfts == cfts) {
2443 list_del(&set->node);
2444 kfree(set);
2445 found = cfts;
2446 break;
2447 }
2448 }
2449
2450 cgroup_cfts_commit(found, false);
2451 cgroup_exit_cftypes(cfts); 2442 cgroup_exit_cftypes(cfts);
2452 return found ? 0 : -ENOENT; 2443 return 0;
2453} 2444}
2454 2445
2455/** 2446/**
@@ -2468,20 +2459,14 @@ int cgroup_rm_cftypes(struct cftype *cfts)
2468 */ 2459 */
2469int cgroup_add_cftypes(struct cgroup_subsys *ss, struct cftype *cfts) 2460int cgroup_add_cftypes(struct cgroup_subsys *ss, struct cftype *cfts)
2470{ 2461{
2471 struct cftype_set *set;
2472 int ret; 2462 int ret;
2473 2463
2474 set = kzalloc(sizeof(*set), GFP_KERNEL);
2475 if (!set)
2476 return -ENOMEM;
2477
2478 ret = cgroup_init_cftypes(ss, cfts); 2464 ret = cgroup_init_cftypes(ss, cfts);
2479 if (ret) 2465 if (ret)
2480 return ret; 2466 return ret;
2481 2467
2482 cgroup_cfts_prepare(); 2468 cgroup_cfts_prepare();
2483 set->cfts = cfts; 2469 list_add_tail(&cfts->node, &ss->cfts);
2484 list_add_tail(&set->node, &ss->cftsets);
2485 ret = cgroup_cfts_commit(cfts, true); 2470 ret = cgroup_cfts_commit(cfts, true);
2486 if (ret) 2471 if (ret)
2487 cgroup_rm_cftypes(cfts); 2472 cgroup_rm_cftypes(cfts);
@@ -3574,13 +3559,13 @@ static int cgroup_populate_dir(struct cgroup *cgrp, unsigned long subsys_mask)
3574 3559
3575 /* process cftsets of each subsystem */ 3560 /* process cftsets of each subsystem */
3576 for_each_subsys(ss, i) { 3561 for_each_subsys(ss, i) {
3577 struct cftype_set *set; 3562 struct cftype *cfts;
3578 3563
3579 if (!test_bit(i, &subsys_mask)) 3564 if (!test_bit(i, &subsys_mask))
3580 continue; 3565 continue;
3581 3566
3582 list_for_each_entry(set, &ss->cftsets, node) { 3567 list_for_each_entry(cfts, &ss->cfts, node) {
3583 ret = cgroup_addrm_files(cgrp, set->cfts, true); 3568 ret = cgroup_addrm_files(cgrp, cfts, true);
3584 if (ret < 0) 3569 if (ret < 0)
3585 goto err; 3570 goto err;
3586 } 3571 }
@@ -4169,7 +4154,7 @@ static void __init cgroup_init_subsys(struct cgroup_subsys *ss)
4169 mutex_lock(&cgroup_tree_mutex); 4154 mutex_lock(&cgroup_tree_mutex);
4170 mutex_lock(&cgroup_mutex); 4155 mutex_lock(&cgroup_mutex);
4171 4156
4172 INIT_LIST_HEAD(&ss->cftsets); 4157 INIT_LIST_HEAD(&ss->cfts);
4173 4158
4174 /* Create the top cgroup state for this subsystem */ 4159 /* Create the top cgroup state for this subsystem */
4175 ss->root = &cgroup_dummy_root; 4160 ss->root = &cgroup_dummy_root;