diff options
Diffstat (limited to 'kernel/cgroup.c')
-rw-r--r-- | kernel/cgroup.c | 31 |
1 files changed, 20 insertions, 11 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index c29831076e7a..e14db9c089b9 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c | |||
@@ -1115,8 +1115,10 @@ static void cgroup_kill_sb(struct super_block *sb) { | |||
1115 | } | 1115 | } |
1116 | write_unlock(&css_set_lock); | 1116 | write_unlock(&css_set_lock); |
1117 | 1117 | ||
1118 | list_del(&root->root_list); | 1118 | if (!list_empty(&root->root_list)) { |
1119 | root_count--; | 1119 | list_del(&root->root_list); |
1120 | root_count--; | ||
1121 | } | ||
1120 | 1122 | ||
1121 | mutex_unlock(&cgroup_mutex); | 1123 | mutex_unlock(&cgroup_mutex); |
1122 | 1124 | ||
@@ -2349,7 +2351,7 @@ static void cgroup_lock_hierarchy(struct cgroupfs_root *root) | |||
2349 | for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) { | 2351 | for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) { |
2350 | struct cgroup_subsys *ss = subsys[i]; | 2352 | struct cgroup_subsys *ss = subsys[i]; |
2351 | if (ss->root == root) | 2353 | if (ss->root == root) |
2352 | mutex_lock_nested(&ss->hierarchy_mutex, i); | 2354 | mutex_lock(&ss->hierarchy_mutex); |
2353 | } | 2355 | } |
2354 | } | 2356 | } |
2355 | 2357 | ||
@@ -2434,7 +2436,9 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry, | |||
2434 | 2436 | ||
2435 | err_remove: | 2437 | err_remove: |
2436 | 2438 | ||
2439 | cgroup_lock_hierarchy(root); | ||
2437 | list_del(&cgrp->sibling); | 2440 | list_del(&cgrp->sibling); |
2441 | cgroup_unlock_hierarchy(root); | ||
2438 | root->number_of_cgroups--; | 2442 | root->number_of_cgroups--; |
2439 | 2443 | ||
2440 | err_destroy: | 2444 | err_destroy: |
@@ -2507,7 +2511,7 @@ static int cgroup_clear_css_refs(struct cgroup *cgrp) | |||
2507 | for_each_subsys(cgrp->root, ss) { | 2511 | for_each_subsys(cgrp->root, ss) { |
2508 | struct cgroup_subsys_state *css = cgrp->subsys[ss->subsys_id]; | 2512 | struct cgroup_subsys_state *css = cgrp->subsys[ss->subsys_id]; |
2509 | int refcnt; | 2513 | int refcnt; |
2510 | do { | 2514 | while (1) { |
2511 | /* We can only remove a CSS with a refcnt==1 */ | 2515 | /* We can only remove a CSS with a refcnt==1 */ |
2512 | refcnt = atomic_read(&css->refcnt); | 2516 | refcnt = atomic_read(&css->refcnt); |
2513 | if (refcnt > 1) { | 2517 | if (refcnt > 1) { |
@@ -2521,7 +2525,10 @@ static int cgroup_clear_css_refs(struct cgroup *cgrp) | |||
2521 | * css_tryget() to spin until we set the | 2525 | * css_tryget() to spin until we set the |
2522 | * CSS_REMOVED bits or abort | 2526 | * CSS_REMOVED bits or abort |
2523 | */ | 2527 | */ |
2524 | } while (atomic_cmpxchg(&css->refcnt, refcnt, 0) != refcnt); | 2528 | if (atomic_cmpxchg(&css->refcnt, refcnt, 0) == refcnt) |
2529 | break; | ||
2530 | cpu_relax(); | ||
2531 | } | ||
2525 | } | 2532 | } |
2526 | done: | 2533 | done: |
2527 | for_each_subsys(cgrp->root, ss) { | 2534 | for_each_subsys(cgrp->root, ss) { |
@@ -2630,6 +2637,7 @@ static void __init cgroup_init_subsys(struct cgroup_subsys *ss) | |||
2630 | BUG_ON(!list_empty(&init_task.tasks)); | 2637 | BUG_ON(!list_empty(&init_task.tasks)); |
2631 | 2638 | ||
2632 | mutex_init(&ss->hierarchy_mutex); | 2639 | mutex_init(&ss->hierarchy_mutex); |
2640 | lockdep_set_class(&ss->hierarchy_mutex, &ss->subsys_key); | ||
2633 | ss->active = 1; | 2641 | ss->active = 1; |
2634 | } | 2642 | } |
2635 | 2643 | ||
@@ -2991,20 +2999,21 @@ int cgroup_clone(struct task_struct *tsk, struct cgroup_subsys *subsys, | |||
2991 | mutex_unlock(&cgroup_mutex); | 2999 | mutex_unlock(&cgroup_mutex); |
2992 | return 0; | 3000 | return 0; |
2993 | } | 3001 | } |
2994 | task_lock(tsk); | ||
2995 | cg = tsk->cgroups; | ||
2996 | parent = task_cgroup(tsk, subsys->subsys_id); | ||
2997 | 3002 | ||
2998 | /* Pin the hierarchy */ | 3003 | /* Pin the hierarchy */ |
2999 | if (!atomic_inc_not_zero(&parent->root->sb->s_active)) { | 3004 | if (!atomic_inc_not_zero(&root->sb->s_active)) { |
3000 | /* We race with the final deactivate_super() */ | 3005 | /* We race with the final deactivate_super() */ |
3001 | mutex_unlock(&cgroup_mutex); | 3006 | mutex_unlock(&cgroup_mutex); |
3002 | return 0; | 3007 | return 0; |
3003 | } | 3008 | } |
3004 | 3009 | ||
3005 | /* Keep the cgroup alive */ | 3010 | /* Keep the cgroup alive */ |
3011 | task_lock(tsk); | ||
3012 | parent = task_cgroup(tsk, subsys->subsys_id); | ||
3013 | cg = tsk->cgroups; | ||
3006 | get_css_set(cg); | 3014 | get_css_set(cg); |
3007 | task_unlock(tsk); | 3015 | task_unlock(tsk); |
3016 | |||
3008 | mutex_unlock(&cgroup_mutex); | 3017 | mutex_unlock(&cgroup_mutex); |
3009 | 3018 | ||
3010 | /* Now do the VFS work to create a cgroup */ | 3019 | /* Now do the VFS work to create a cgroup */ |
@@ -3043,7 +3052,7 @@ int cgroup_clone(struct task_struct *tsk, struct cgroup_subsys *subsys, | |||
3043 | mutex_unlock(&inode->i_mutex); | 3052 | mutex_unlock(&inode->i_mutex); |
3044 | put_css_set(cg); | 3053 | put_css_set(cg); |
3045 | 3054 | ||
3046 | deactivate_super(parent->root->sb); | 3055 | deactivate_super(root->sb); |
3047 | /* The cgroup is still accessible in the VFS, but | 3056 | /* The cgroup is still accessible in the VFS, but |
3048 | * we're not going to try to rmdir() it at this | 3057 | * we're not going to try to rmdir() it at this |
3049 | * point. */ | 3058 | * point. */ |
@@ -3069,7 +3078,7 @@ int cgroup_clone(struct task_struct *tsk, struct cgroup_subsys *subsys, | |||
3069 | mutex_lock(&cgroup_mutex); | 3078 | mutex_lock(&cgroup_mutex); |
3070 | put_css_set(cg); | 3079 | put_css_set(cg); |
3071 | mutex_unlock(&cgroup_mutex); | 3080 | mutex_unlock(&cgroup_mutex); |
3072 | deactivate_super(parent->root->sb); | 3081 | deactivate_super(root->sb); |
3073 | return ret; | 3082 | return ret; |
3074 | } | 3083 | } |
3075 | 3084 | ||