aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/cgroup.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/cgroup.c')
-rw-r--r--kernel/cgroup.c248
1 files changed, 199 insertions, 49 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index ccec722213a4..8ba680985335 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -207,6 +207,7 @@ struct cg_cgroup_link {
207 * cgroup, anchored on cgroup->css_sets 207 * cgroup, anchored on cgroup->css_sets
208 */ 208 */
209 struct list_head cgrp_link_list; 209 struct list_head cgrp_link_list;
210 struct cgroup *cgrp;
210 /* 211 /*
211 * List running through cg_cgroup_links pointing at a 212 * List running through cg_cgroup_links pointing at a
212 * single css_set object, anchored on css_set->cg_links 213 * single css_set object, anchored on css_set->cg_links
@@ -233,8 +234,11 @@ static int cgroup_subsys_init_idr(struct cgroup_subsys *ss);
233static DEFINE_RWLOCK(css_set_lock); 234static DEFINE_RWLOCK(css_set_lock);
234static int css_set_count; 235static int css_set_count;
235 236
236/* hash table for cgroup groups. This improves the performance to 237/*
237 * find an existing css_set */ 238 * hash table for cgroup groups. This improves the performance to find
239 * an existing css_set. This hash doesn't (currently) take into
240 * account cgroups in empty hierarchies.
241 */
238#define CSS_SET_HASH_BITS 7 242#define CSS_SET_HASH_BITS 7
239#define CSS_SET_TABLE_SIZE (1 << CSS_SET_HASH_BITS) 243#define CSS_SET_TABLE_SIZE (1 << CSS_SET_HASH_BITS)
240static struct hlist_head css_set_table[CSS_SET_TABLE_SIZE]; 244static struct hlist_head css_set_table[CSS_SET_TABLE_SIZE];
@@ -344,6 +348,78 @@ static inline void put_css_set_taskexit(struct css_set *cg)
344} 348}
345 349
346/* 350/*
351 * compare_css_sets - helper function for find_existing_css_set().
352 * @cg: candidate css_set being tested
353 * @old_cg: existing css_set for a task
354 * @new_cgrp: cgroup that's being entered by the task
355 * @template: desired set of css pointers in css_set (pre-calculated)
356 *
357 * Returns true if "cg" matches "old_cg" except for the hierarchy
358 * which "new_cgrp" belongs to, for which it should match "new_cgrp".
359 */
360static bool compare_css_sets(struct css_set *cg,
361 struct css_set *old_cg,
362 struct cgroup *new_cgrp,
363 struct cgroup_subsys_state *template[])
364{
365 struct list_head *l1, *l2;
366
367 if (memcmp(template, cg->subsys, sizeof(cg->subsys))) {
368 /* Not all subsystems matched */
369 return false;
370 }
371
372 /*
373 * Compare cgroup pointers in order to distinguish between
374 * different cgroups in heirarchies with no subsystems. We
375 * could get by with just this check alone (and skip the
376 * memcmp above) but on most setups the memcmp check will
377 * avoid the need for this more expensive check on almost all
378 * candidates.
379 */
380
381 l1 = &cg->cg_links;
382 l2 = &old_cg->cg_links;
383 while (1) {
384 struct cg_cgroup_link *cgl1, *cgl2;
385 struct cgroup *cg1, *cg2;
386
387 l1 = l1->next;
388 l2 = l2->next;
389 /* See if we reached the end - both lists are equal length. */
390 if (l1 == &cg->cg_links) {
391 BUG_ON(l2 != &old_cg->cg_links);
392 break;
393 } else {
394 BUG_ON(l2 == &old_cg->cg_links);
395 }
396 /* Locate the cgroups associated with these links. */
397 cgl1 = list_entry(l1, struct cg_cgroup_link, cg_link_list);
398 cgl2 = list_entry(l2, struct cg_cgroup_link, cg_link_list);
399 cg1 = cgl1->cgrp;
400 cg2 = cgl2->cgrp;
401 /* Hierarchies should be linked in the same order. */
402 BUG_ON(cg1->root != cg2->root);
403
404 /*
405 * If this hierarchy is the hierarchy of the cgroup
406 * that's changing, then we need to check that this
407 * css_set points to the new cgroup; if it's any other
408 * hierarchy, then this css_set should point to the
409 * same cgroup as the old css_set.
410 */
411 if (cg1->root == new_cgrp->root) {
412 if (cg1 != new_cgrp)
413 return false;
414 } else {
415 if (cg1 != cg2)
416 return false;
417 }
418 }
419 return true;
420}
421
422/*
347 * find_existing_css_set() is a helper for 423 * find_existing_css_set() is a helper for
348 * find_css_set(), and checks to see whether an existing 424 * find_css_set(), and checks to see whether an existing
349 * css_set is suitable. 425 * css_set is suitable.
@@ -384,10 +460,11 @@ static struct css_set *find_existing_css_set(
384 460
385 hhead = css_set_hash(template); 461 hhead = css_set_hash(template);
386 hlist_for_each_entry(cg, node, hhead, hlist) { 462 hlist_for_each_entry(cg, node, hhead, hlist) {
387 if (!memcmp(template, cg->subsys, sizeof(cg->subsys))) { 463 if (!compare_css_sets(cg, oldcg, cgrp, template))
388 /* All subsystems matched */ 464 continue;
389 return cg; 465
390 } 466 /* This css_set matches what we need */
467 return cg;
391 } 468 }
392 469
393 /* No existing cgroup group matched */ 470 /* No existing cgroup group matched */
@@ -441,8 +518,13 @@ static void link_css_set(struct list_head *tmp_cg_links,
441 link = list_first_entry(tmp_cg_links, struct cg_cgroup_link, 518 link = list_first_entry(tmp_cg_links, struct cg_cgroup_link,
442 cgrp_link_list); 519 cgrp_link_list);
443 link->cg = cg; 520 link->cg = cg;
521 link->cgrp = cgrp;
444 list_move(&link->cgrp_link_list, &cgrp->css_sets); 522 list_move(&link->cgrp_link_list, &cgrp->css_sets);
445 list_add(&link->cg_link_list, &cg->cg_links); 523 /*
524 * Always add links to the tail of the list so that the list
525 * is sorted by order of hierarchy creation
526 */
527 list_add_tail(&link->cg_link_list, &cg->cg_links);
446} 528}
447 529
448/* 530/*
@@ -462,6 +544,7 @@ static struct css_set *find_css_set(
462 struct list_head tmp_cg_links; 544 struct list_head tmp_cg_links;
463 545
464 struct hlist_head *hhead; 546 struct hlist_head *hhead;
547 struct cg_cgroup_link *link;
465 548
466 /* First see if we already have a cgroup group that matches 549 /* First see if we already have a cgroup group that matches
467 * the desired set */ 550 * the desired set */
@@ -497,18 +580,14 @@ static struct css_set *find_css_set(
497 /* Add reference counts and links from the new css_set. */ 580 /* Add reference counts and links from the new css_set. */
498 for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) { 581 for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
499 struct cgroup *cgrp = res->subsys[i]->cgroup; 582 struct cgroup *cgrp = res->subsys[i]->cgroup;
500 struct cgroup_subsys *ss = subsys[i];
501 atomic_inc(&cgrp->count); 583 atomic_inc(&cgrp->count);
502 /*
503 * We want to add a link once per cgroup, so we
504 * only do it for the first subsystem in each
505 * hierarchy
506 */
507 if (ss->root->subsys_list.next == &ss->sibling)
508 link_css_set(&tmp_cg_links, res, cgrp);
509 } 584 }
510 if (list_empty(&rootnode.subsys_list)) 585 list_for_each_entry(link, &oldcg->cg_links, cg_link_list) {
511 link_css_set(&tmp_cg_links, res, dummytop); 586 struct cgroup *c = link->cgrp;
587 if (c->root == cgrp->root)
588 c = cgrp;
589 link_css_set(&tmp_cg_links, res, c);
590 }
512 591
513 BUG_ON(!list_empty(&tmp_cg_links)); 592 BUG_ON(!list_empty(&tmp_cg_links));
514 593
@@ -524,6 +603,41 @@ static struct css_set *find_css_set(
524} 603}
525 604
526/* 605/*
606 * Return the cgroup for "task" from the given hierarchy. Must be
607 * called with cgroup_mutex held.
608 */
609static struct cgroup *task_cgroup_from_root(struct task_struct *task,
610 struct cgroupfs_root *root)
611{
612 struct css_set *css;
613 struct cgroup *res = NULL;
614
615 BUG_ON(!mutex_is_locked(&cgroup_mutex));
616 read_lock(&css_set_lock);
617 /*
618 * No need to lock the task - since we hold cgroup_mutex the
619 * task can't change groups, so the only thing that can happen
620 * is that it exits and its css is set back to init_css_set.
621 */
622 css = task->cgroups;
623 if (css == &init_css_set) {
624 res = &root->top_cgroup;
625 } else {
626 struct cg_cgroup_link *link;
627 list_for_each_entry(link, &css->cg_links, cg_link_list) {
628 struct cgroup *c = link->cgrp;
629 if (c->root == root) {
630 res = c;
631 break;
632 }
633 }
634 }
635 read_unlock(&css_set_lock);
636 BUG_ON(!res);
637 return res;
638}
639
640/*
527 * There is one global cgroup mutex. We also require taking 641 * There is one global cgroup mutex. We also require taking
528 * task_lock() when dereferencing a task's cgroup subsys pointers. 642 * task_lock() when dereferencing a task's cgroup subsys pointers.
529 * See "The task_lock() exception", at the end of this comment. 643 * See "The task_lock() exception", at the end of this comment.
@@ -1361,27 +1475,6 @@ int cgroup_path(const struct cgroup *cgrp, char *buf, int buflen)
1361 return 0; 1475 return 0;
1362} 1476}
1363 1477
1364/*
1365 * Return the first subsystem attached to a cgroup's hierarchy, and
1366 * its subsystem id.
1367 */
1368
1369static void get_first_subsys(const struct cgroup *cgrp,
1370 struct cgroup_subsys_state **css, int *subsys_id)
1371{
1372 const struct cgroupfs_root *root = cgrp->root;
1373 const struct cgroup_subsys *test_ss;
1374 BUG_ON(list_empty(&root->subsys_list));
1375 test_ss = list_entry(root->subsys_list.next,
1376 struct cgroup_subsys, sibling);
1377 if (css) {
1378 *css = cgrp->subsys[test_ss->subsys_id];
1379 BUG_ON(!*css);
1380 }
1381 if (subsys_id)
1382 *subsys_id = test_ss->subsys_id;
1383}
1384
1385/** 1478/**
1386 * cgroup_attach_task - attach task 'tsk' to cgroup 'cgrp' 1479 * cgroup_attach_task - attach task 'tsk' to cgroup 'cgrp'
1387 * @cgrp: the cgroup the task is attaching to 1480 * @cgrp: the cgroup the task is attaching to
@@ -1398,12 +1491,9 @@ int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk)
1398 struct css_set *cg; 1491 struct css_set *cg;
1399 struct css_set *newcg; 1492 struct css_set *newcg;
1400 struct cgroupfs_root *root = cgrp->root; 1493 struct cgroupfs_root *root = cgrp->root;
1401 int subsys_id;
1402
1403 get_first_subsys(cgrp, NULL, &subsys_id);
1404 1494
1405 /* Nothing to do if the task is already in that cgroup */ 1495 /* Nothing to do if the task is already in that cgroup */
1406 oldcgrp = task_cgroup(tsk, subsys_id); 1496 oldcgrp = task_cgroup_from_root(tsk, root);
1407 if (cgrp == oldcgrp) 1497 if (cgrp == oldcgrp)
1408 return 0; 1498 return 0;
1409 1499
@@ -1961,7 +2051,7 @@ int cgroup_task_count(const struct cgroup *cgrp)
1961 * the start of a css_set 2051 * the start of a css_set
1962 */ 2052 */
1963static void cgroup_advance_iter(struct cgroup *cgrp, 2053static void cgroup_advance_iter(struct cgroup *cgrp,
1964 struct cgroup_iter *it) 2054 struct cgroup_iter *it)
1965{ 2055{
1966 struct list_head *l = it->cg_link; 2056 struct list_head *l = it->cg_link;
1967 struct cg_cgroup_link *link; 2057 struct cg_cgroup_link *link;
@@ -2964,6 +3054,7 @@ int __init cgroup_init_early(void)
2964 init_task.cgroups = &init_css_set; 3054 init_task.cgroups = &init_css_set;
2965 3055
2966 init_css_set_link.cg = &init_css_set; 3056 init_css_set_link.cg = &init_css_set;
3057 init_css_set_link.cgrp = dummytop;
2967 list_add(&init_css_set_link.cgrp_link_list, 3058 list_add(&init_css_set_link.cgrp_link_list,
2968 &rootnode.top_cgroup.css_sets); 3059 &rootnode.top_cgroup.css_sets);
2969 list_add(&init_css_set_link.cg_link_list, 3060 list_add(&init_css_set_link.cg_link_list,
@@ -3071,7 +3162,6 @@ static int proc_cgroup_show(struct seq_file *m, void *v)
3071 for_each_active_root(root) { 3162 for_each_active_root(root) {
3072 struct cgroup_subsys *ss; 3163 struct cgroup_subsys *ss;
3073 struct cgroup *cgrp; 3164 struct cgroup *cgrp;
3074 int subsys_id;
3075 int count = 0; 3165 int count = 0;
3076 3166
3077 seq_printf(m, "%lu:", root->subsys_bits); 3167 seq_printf(m, "%lu:", root->subsys_bits);
@@ -3081,8 +3171,7 @@ static int proc_cgroup_show(struct seq_file *m, void *v)
3081 seq_printf(m, "%sname=%s", count ? "," : "", 3171 seq_printf(m, "%sname=%s", count ? "," : "",
3082 root->name); 3172 root->name);
3083 seq_putc(m, ':'); 3173 seq_putc(m, ':');
3084 get_first_subsys(&root->top_cgroup, NULL, &subsys_id); 3174 cgrp = task_cgroup_from_root(tsk, root);
3085 cgrp = task_cgroup(tsk, subsys_id);
3086 retval = cgroup_path(cgrp, buf, PAGE_SIZE); 3175 retval = cgroup_path(cgrp, buf, PAGE_SIZE);
3087 if (retval < 0) 3176 if (retval < 0)
3088 goto out_unlock; 3177 goto out_unlock;
@@ -3408,13 +3497,11 @@ int cgroup_is_descendant(const struct cgroup *cgrp, struct task_struct *task)
3408{ 3497{
3409 int ret; 3498 int ret;
3410 struct cgroup *target; 3499 struct cgroup *target;
3411 int subsys_id;
3412 3500
3413 if (cgrp == dummytop) 3501 if (cgrp == dummytop)
3414 return 1; 3502 return 1;
3415 3503
3416 get_first_subsys(cgrp, NULL, &subsys_id); 3504 target = task_cgroup_from_root(task, cgrp->root);
3417 target = task_cgroup(task, subsys_id);
3418 while (cgrp != target && cgrp!= cgrp->top_cgroup) 3505 while (cgrp != target && cgrp!= cgrp->top_cgroup)
3419 cgrp = cgrp->parent; 3506 cgrp = cgrp->parent;
3420 ret = (cgrp == target); 3507 ret = (cgrp == target);
@@ -3824,6 +3911,59 @@ static u64 current_css_set_refcount_read(struct cgroup *cont,
3824 return count; 3911 return count;
3825} 3912}
3826 3913
3914static int current_css_set_cg_links_read(struct cgroup *cont,
3915 struct cftype *cft,
3916 struct seq_file *seq)
3917{
3918 struct cg_cgroup_link *link;
3919 struct css_set *cg;
3920
3921 read_lock(&css_set_lock);
3922 rcu_read_lock();
3923 cg = rcu_dereference(current->cgroups);
3924 list_for_each_entry(link, &cg->cg_links, cg_link_list) {
3925 struct cgroup *c = link->cgrp;
3926 const char *name;
3927
3928 if (c->dentry)
3929 name = c->dentry->d_name.name;
3930 else
3931 name = "?";
3932 seq_printf(seq, "Root %lu group %s\n",
3933 c->root->subsys_bits, name);
3934 }
3935 rcu_read_unlock();
3936 read_unlock(&css_set_lock);
3937 return 0;
3938}
3939
3940#define MAX_TASKS_SHOWN_PER_CSS 25
3941static int cgroup_css_links_read(struct cgroup *cont,
3942 struct cftype *cft,
3943 struct seq_file *seq)
3944{
3945 struct cg_cgroup_link *link;
3946
3947 read_lock(&css_set_lock);
3948 list_for_each_entry(link, &cont->css_sets, cgrp_link_list) {
3949 struct css_set *cg = link->cg;
3950 struct task_struct *task;
3951 int count = 0;
3952 seq_printf(seq, "css_set %p\n", cg);
3953 list_for_each_entry(task, &cg->tasks, cg_list) {
3954 if (count++ > MAX_TASKS_SHOWN_PER_CSS) {
3955 seq_puts(seq, " ...\n");
3956 break;
3957 } else {
3958 seq_printf(seq, " task %d\n",
3959 task_pid_vnr(task));
3960 }
3961 }
3962 }
3963 read_unlock(&css_set_lock);
3964 return 0;
3965}
3966
3827static u64 releasable_read(struct cgroup *cgrp, struct cftype *cft) 3967static u64 releasable_read(struct cgroup *cgrp, struct cftype *cft)
3828{ 3968{
3829 return test_bit(CGRP_RELEASABLE, &cgrp->flags); 3969 return test_bit(CGRP_RELEASABLE, &cgrp->flags);
@@ -3850,6 +3990,16 @@ static struct cftype debug_files[] = {
3850 }, 3990 },
3851 3991
3852 { 3992 {
3993 .name = "current_css_set_cg_links",
3994 .read_seq_string = current_css_set_cg_links_read,
3995 },
3996
3997 {
3998 .name = "cgroup_css_links",
3999 .read_seq_string = cgroup_css_links_read,
4000 },
4001
4002 {
3853 .name = "releasable", 4003 .name = "releasable",
3854 .read_u64 = releasable_read, 4004 .read_u64 = releasable_read,
3855 }, 4005 },