aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Blum <bblum@andrew.cmu.edu>2010-03-10 18:22:09 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2010-03-12 18:52:36 -0500
commite6a1105ba08b265023dd71a4174fb4a29ebc7083 (patch)
treec171a012df4364b0feac5d6f1bf8c354164ab0f9
parentaae8aab40367036931608fdaf9e2dc568b516f19 (diff)
cgroups: subsystem module loading interface
Add interface between cgroups subsystem management and module loading This patch implements rudimentary module-loading support for cgroups - namely, a cgroup_load_subsys (similar to cgroup_init_subsys) for use as a module initcall, and a struct module pointer in struct cgroup_subsys. Several functions that might be wanted by modules have had EXPORT_SYMBOL added to them, but it's unclear exactly which functions want it and which won't. Signed-off-by: Ben Blum <bblum@andrew.cmu.edu> Acked-by: Li Zefan <lizf@cn.fujitsu.com> Cc: Paul Menage <menage@google.com> Cc: "David S. Miller" <davem@davemloft.net> Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Cc: Lai Jiangshan <laijs@cn.fujitsu.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--Documentation/cgroups/cgroups.txt4
-rw-r--r--include/linux/cgroup.h4
-rw-r--r--kernel/cgroup.c150
3 files changed, 153 insertions, 5 deletions
diff --git a/Documentation/cgroups/cgroups.txt b/Documentation/cgroups/cgroups.txt
index d45082653e3d..ae8a037a761e 100644
--- a/Documentation/cgroups/cgroups.txt
+++ b/Documentation/cgroups/cgroups.txt
@@ -488,6 +488,10 @@ Each subsystem should:
488- add an entry in linux/cgroup_subsys.h 488- add an entry in linux/cgroup_subsys.h
489- define a cgroup_subsys object called <name>_subsys 489- define a cgroup_subsys object called <name>_subsys
490 490
491If a subsystem can be compiled as a module, it should also have in its
492module initcall a call to cgroup_load_subsys(&its_subsys_struct). It
493should also set its_subsys.module = THIS_MODULE in its .c file.
494
491Each subsystem may export the following methods. The only mandatory 495Each subsystem may export the following methods. The only mandatory
492methods are create/destroy. Any others that are null are presumed to 496methods are create/destroy. Any others that are null are presumed to
493be successful no-ops. 497be successful no-ops.
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
index 28319a9fe569..402ce477c47e 100644
--- a/include/linux/cgroup.h
+++ b/include/linux/cgroup.h
@@ -37,6 +37,7 @@ extern void cgroup_post_fork(struct task_struct *p);
37extern void cgroup_exit(struct task_struct *p, int run_callbacks); 37extern void cgroup_exit(struct task_struct *p, int run_callbacks);
38extern int cgroupstats_build(struct cgroupstats *stats, 38extern int cgroupstats_build(struct cgroupstats *stats,
39 struct dentry *dentry); 39 struct dentry *dentry);
40extern int cgroup_load_subsys(struct cgroup_subsys *ss);
40 41
41extern const struct file_operations proc_cgroup_operations; 42extern const struct file_operations proc_cgroup_operations;
42 43
@@ -486,6 +487,9 @@ struct cgroup_subsys {
486 /* used when use_id == true */ 487 /* used when use_id == true */
487 struct idr idr; 488 struct idr idr;
488 spinlock_t id_lock; 489 spinlock_t id_lock;
490
491 /* should be defined only by modular subsystems */
492 struct module *module;
489}; 493};
490 494
491#define SUBSYS(_x) extern struct cgroup_subsys _x ## _subsys; 495#define SUBSYS(_x) extern struct cgroup_subsys _x ## _subsys;
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index c92fb9549358..2cae38e64c59 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -44,6 +44,7 @@
44#include <linux/string.h> 44#include <linux/string.h>
45#include <linux/sort.h> 45#include <linux/sort.h>
46#include <linux/kmod.h> 46#include <linux/kmod.h>
47#include <linux/module.h>
47#include <linux/delayacct.h> 48#include <linux/delayacct.h>
48#include <linux/cgroupstats.h> 49#include <linux/cgroupstats.h>
49#include <linux/hash.h> 50#include <linux/hash.h>
@@ -254,7 +255,8 @@ struct cg_cgroup_link {
254static struct css_set init_css_set; 255static struct css_set init_css_set;
255static struct cg_cgroup_link init_css_set_link; 256static struct cg_cgroup_link init_css_set_link;
256 257
257static int cgroup_subsys_init_idr(struct cgroup_subsys *ss); 258static int cgroup_init_idr(struct cgroup_subsys *ss,
259 struct cgroup_subsys_state *css);
258 260
259/* css_set_lock protects the list of css_set objects, and the 261/* css_set_lock protects the list of css_set objects, and the
260 * chain of tasks off each css_set. Nests outside task->alloc_lock 262 * chain of tasks off each css_set. Nests outside task->alloc_lock
@@ -2125,6 +2127,7 @@ int cgroup_add_file(struct cgroup *cgrp,
2125 error = PTR_ERR(dentry); 2127 error = PTR_ERR(dentry);
2126 return error; 2128 return error;
2127} 2129}
2130EXPORT_SYMBOL_GPL(cgroup_add_file);
2128 2131
2129int cgroup_add_files(struct cgroup *cgrp, 2132int cgroup_add_files(struct cgroup *cgrp,
2130 struct cgroup_subsys *subsys, 2133 struct cgroup_subsys *subsys,
@@ -2139,6 +2142,7 @@ int cgroup_add_files(struct cgroup *cgrp,
2139 } 2142 }
2140 return 0; 2143 return 0;
2141} 2144}
2145EXPORT_SYMBOL_GPL(cgroup_add_files);
2142 2146
2143/** 2147/**
2144 * cgroup_task_count - count the number of tasks in a cgroup. 2148 * cgroup_task_count - count the number of tasks in a cgroup.
@@ -3292,7 +3296,144 @@ static void __init cgroup_init_subsys(struct cgroup_subsys *ss)
3292 mutex_init(&ss->hierarchy_mutex); 3296 mutex_init(&ss->hierarchy_mutex);
3293 lockdep_set_class(&ss->hierarchy_mutex, &ss->subsys_key); 3297 lockdep_set_class(&ss->hierarchy_mutex, &ss->subsys_key);
3294 ss->active = 1; 3298 ss->active = 1;
3299
3300 /* this function shouldn't be used with modular subsystems, since they
3301 * need to register a subsys_id, among other things */
3302 BUG_ON(ss->module);
3303}
3304
3305/**
3306 * cgroup_load_subsys: load and register a modular subsystem at runtime
3307 * @ss: the subsystem to load
3308 *
3309 * This function should be called in a modular subsystem's initcall. If the
3310 * subsytem is built as a module, it will be assigned a new subsys_id and set
3311 * up for use. If the subsystem is built-in anyway, work is delegated to the
3312 * simpler cgroup_init_subsys.
3313 */
3314int __init_or_module cgroup_load_subsys(struct cgroup_subsys *ss)
3315{
3316 int i;
3317 struct cgroup_subsys_state *css;
3318
3319 /* check name and function validity */
3320 if (ss->name == NULL || strlen(ss->name) > MAX_CGROUP_TYPE_NAMELEN ||
3321 ss->create == NULL || ss->destroy == NULL)
3322 return -EINVAL;
3323
3324 /*
3325 * we don't support callbacks in modular subsystems. this check is
3326 * before the ss->module check for consistency; a subsystem that could
3327 * be a module should still have no callbacks even if the user isn't
3328 * compiling it as one.
3329 */
3330 if (ss->fork || ss->exit)
3331 return -EINVAL;
3332
3333 /*
3334 * an optionally modular subsystem is built-in: we want to do nothing,
3335 * since cgroup_init_subsys will have already taken care of it.
3336 */
3337 if (ss->module == NULL) {
3338 /* a few sanity checks */
3339 BUG_ON(ss->subsys_id >= CGROUP_BUILTIN_SUBSYS_COUNT);
3340 BUG_ON(subsys[ss->subsys_id] != ss);
3341 return 0;
3342 }
3343
3344 /*
3345 * need to register a subsys id before anything else - for example,
3346 * init_cgroup_css needs it.
3347 */
3348 mutex_lock(&cgroup_mutex);
3349 /* find the first empty slot in the array */
3350 for (i = CGROUP_BUILTIN_SUBSYS_COUNT; i < CGROUP_SUBSYS_COUNT; i++) {
3351 if (subsys[i] == NULL)
3352 break;
3353 }
3354 if (i == CGROUP_SUBSYS_COUNT) {
3355 /* maximum number of subsystems already registered! */
3356 mutex_unlock(&cgroup_mutex);
3357 return -EBUSY;
3358 }
3359 /* assign ourselves the subsys_id */
3360 ss->subsys_id = i;
3361 subsys[i] = ss;
3362
3363 /*
3364 * no ss->create seems to need anything important in the ss struct, so
3365 * this can happen first (i.e. before the rootnode attachment).
3366 */
3367 css = ss->create(ss, dummytop);
3368 if (IS_ERR(css)) {
3369 /* failure case - need to deassign the subsys[] slot. */
3370 subsys[i] = NULL;
3371 mutex_unlock(&cgroup_mutex);
3372 return PTR_ERR(css);
3373 }
3374
3375 list_add(&ss->sibling, &rootnode.subsys_list);
3376 ss->root = &rootnode;
3377
3378 /* our new subsystem will be attached to the dummy hierarchy. */
3379 init_cgroup_css(css, ss, dummytop);
3380 /* init_idr must be after init_cgroup_css because it sets css->id. */
3381 if (ss->use_id) {
3382 int ret = cgroup_init_idr(ss, css);
3383 if (ret) {
3384 dummytop->subsys[ss->subsys_id] = NULL;
3385 ss->destroy(ss, dummytop);
3386 subsys[i] = NULL;
3387 mutex_unlock(&cgroup_mutex);
3388 return ret;
3389 }
3390 }
3391
3392 /*
3393 * Now we need to entangle the css into the existing css_sets. unlike
3394 * in cgroup_init_subsys, there are now multiple css_sets, so each one
3395 * will need a new pointer to it; done by iterating the css_set_table.
3396 * furthermore, modifying the existing css_sets will corrupt the hash
3397 * table state, so each changed css_set will need its hash recomputed.
3398 * this is all done under the css_set_lock.
3399 */
3400 write_lock(&css_set_lock);
3401 for (i = 0; i < CSS_SET_TABLE_SIZE; i++) {
3402 struct css_set *cg;
3403 struct hlist_node *node, *tmp;
3404 struct hlist_head *bucket = &css_set_table[i], *new_bucket;
3405
3406 hlist_for_each_entry_safe(cg, node, tmp, bucket, hlist) {
3407 /* skip entries that we already rehashed */
3408 if (cg->subsys[ss->subsys_id])
3409 continue;
3410 /* remove existing entry */
3411 hlist_del(&cg->hlist);
3412 /* set new value */
3413 cg->subsys[ss->subsys_id] = css;
3414 /* recompute hash and restore entry */
3415 new_bucket = css_set_hash(cg->subsys);
3416 hlist_add_head(&cg->hlist, new_bucket);
3417 }
3418 }
3419 write_unlock(&css_set_lock);
3420
3421 mutex_init(&ss->hierarchy_mutex);
3422 lockdep_set_class(&ss->hierarchy_mutex, &ss->subsys_key);
3423 ss->active = 1;
3424
3425 /*
3426 * pin the subsystem's module so it doesn't go away. this shouldn't
3427 * fail, since the module's initcall calls us.
3428 * TODO: with module unloading, move this elsewhere
3429 */
3430 BUG_ON(!try_module_get(ss->module));
3431
3432 /* success! */
3433 mutex_unlock(&cgroup_mutex);
3434 return 0;
3295} 3435}
3436EXPORT_SYMBOL_GPL(cgroup_load_subsys);
3296 3437
3297/** 3438/**
3298 * cgroup_init_early - cgroup initialization at system boot 3439 * cgroup_init_early - cgroup initialization at system boot
@@ -3364,7 +3505,7 @@ int __init cgroup_init(void)
3364 if (!ss->early_init) 3505 if (!ss->early_init)
3365 cgroup_init_subsys(ss); 3506 cgroup_init_subsys(ss);
3366 if (ss->use_id) 3507 if (ss->use_id)
3367 cgroup_subsys_init_idr(ss); 3508 cgroup_init_idr(ss, init_css_set.subsys[ss->subsys_id]);
3368 } 3509 }
3369 3510
3370 /* Add init_css_set to the hash table */ 3511 /* Add init_css_set to the hash table */
@@ -4033,15 +4174,14 @@ err_out:
4033 4174
4034} 4175}
4035 4176
4036static int __init cgroup_subsys_init_idr(struct cgroup_subsys *ss) 4177static int __init_or_module cgroup_init_idr(struct cgroup_subsys *ss,
4178 struct cgroup_subsys_state *rootcss)
4037{ 4179{
4038 struct css_id *newid; 4180 struct css_id *newid;
4039 struct cgroup_subsys_state *rootcss;
4040 4181
4041 spin_lock_init(&ss->id_lock); 4182 spin_lock_init(&ss->id_lock);
4042 idr_init(&ss->idr); 4183 idr_init(&ss->idr);
4043 4184
4044 rootcss = init_css_set.subsys[ss->subsys_id];
4045 newid = get_new_cssid(ss, 0); 4185 newid = get_new_cssid(ss, 0);
4046 if (IS_ERR(newid)) 4186 if (IS_ERR(newid))
4047 return PTR_ERR(newid); 4187 return PTR_ERR(newid);