diff options
author | Hugh Dickins <hughd@google.com> | 2012-03-21 19:34:21 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-03-21 20:55:01 -0400 |
commit | 42aee6c495e07dba7410b863a360db6bb9ec6d66 (patch) | |
tree | d014b2b5c7aa9d1a1f13686fa06699f9f734ee1c /kernel | |
parent | 9f7de8275b46d9d11b1505adbfe6c2bb48df4741 (diff) |
cgroup: revert ss_id_lock to spinlock
Commit c1e2ee2dc436 ("memcg: replace ss->id_lock with a rwlock") has now
been seen to cause the unfair behavior we should have expected from
converting a spinlock to an rwlock: softlockup in cgroup_mkdir(), whose
get_new_cssid() is waiting for the wlock, while there are 19 tasks using
the rlock in css_get_next() to get on with their memcg workload (in an
artificial test, admittedly). Yet lib/idr.c was made suitable for RCU
way back: revert that commit, restoring ss->id_lock to a spinlock.
Signed-off-by: Hugh Dickins <hughd@google.com>
Acked-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Acked-by: Li Zefan <lizf@cn.fujitsu.com>
Cc: Eric Dumazet <eric.dumazet@gmail.com>
Acked-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/cgroup.c | 18 |
1 files changed, 9 insertions, 9 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index c6877fe9a831..8eb90f25bd7b 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c | |||
@@ -4885,9 +4885,9 @@ void free_css_id(struct cgroup_subsys *ss, struct cgroup_subsys_state *css) | |||
4885 | 4885 | ||
4886 | rcu_assign_pointer(id->css, NULL); | 4886 | rcu_assign_pointer(id->css, NULL); |
4887 | rcu_assign_pointer(css->id, NULL); | 4887 | rcu_assign_pointer(css->id, NULL); |
4888 | write_lock(&ss->id_lock); | 4888 | spin_lock(&ss->id_lock); |
4889 | idr_remove(&ss->idr, id->id); | 4889 | idr_remove(&ss->idr, id->id); |
4890 | write_unlock(&ss->id_lock); | 4890 | spin_unlock(&ss->id_lock); |
4891 | kfree_rcu(id, rcu_head); | 4891 | kfree_rcu(id, rcu_head); |
4892 | } | 4892 | } |
4893 | EXPORT_SYMBOL_GPL(free_css_id); | 4893 | EXPORT_SYMBOL_GPL(free_css_id); |
@@ -4913,10 +4913,10 @@ static struct css_id *get_new_cssid(struct cgroup_subsys *ss, int depth) | |||
4913 | error = -ENOMEM; | 4913 | error = -ENOMEM; |
4914 | goto err_out; | 4914 | goto err_out; |
4915 | } | 4915 | } |
4916 | write_lock(&ss->id_lock); | 4916 | spin_lock(&ss->id_lock); |
4917 | /* Don't use 0. allocates an ID of 1-65535 */ | 4917 | /* Don't use 0. allocates an ID of 1-65535 */ |
4918 | error = idr_get_new_above(&ss->idr, newid, 1, &myid); | 4918 | error = idr_get_new_above(&ss->idr, newid, 1, &myid); |
4919 | write_unlock(&ss->id_lock); | 4919 | spin_unlock(&ss->id_lock); |
4920 | 4920 | ||
4921 | /* Returns error when there are no free spaces for new ID.*/ | 4921 | /* Returns error when there are no free spaces for new ID.*/ |
4922 | if (error) { | 4922 | if (error) { |
@@ -4931,9 +4931,9 @@ static struct css_id *get_new_cssid(struct cgroup_subsys *ss, int depth) | |||
4931 | return newid; | 4931 | return newid; |
4932 | remove_idr: | 4932 | remove_idr: |
4933 | error = -ENOSPC; | 4933 | error = -ENOSPC; |
4934 | write_lock(&ss->id_lock); | 4934 | spin_lock(&ss->id_lock); |
4935 | idr_remove(&ss->idr, myid); | 4935 | idr_remove(&ss->idr, myid); |
4936 | write_unlock(&ss->id_lock); | 4936 | spin_unlock(&ss->id_lock); |
4937 | err_out: | 4937 | err_out: |
4938 | kfree(newid); | 4938 | kfree(newid); |
4939 | return ERR_PTR(error); | 4939 | return ERR_PTR(error); |
@@ -4945,7 +4945,7 @@ static int __init_or_module cgroup_init_idr(struct cgroup_subsys *ss, | |||
4945 | { | 4945 | { |
4946 | struct css_id *newid; | 4946 | struct css_id *newid; |
4947 | 4947 | ||
4948 | rwlock_init(&ss->id_lock); | 4948 | spin_lock_init(&ss->id_lock); |
4949 | idr_init(&ss->idr); | 4949 | idr_init(&ss->idr); |
4950 | 4950 | ||
4951 | newid = get_new_cssid(ss, 0); | 4951 | newid = get_new_cssid(ss, 0); |
@@ -5040,9 +5040,9 @@ css_get_next(struct cgroup_subsys *ss, int id, | |||
5040 | * scan next entry from bitmap(tree), tmpid is updated after | 5040 | * scan next entry from bitmap(tree), tmpid is updated after |
5041 | * idr_get_next(). | 5041 | * idr_get_next(). |
5042 | */ | 5042 | */ |
5043 | read_lock(&ss->id_lock); | 5043 | spin_lock(&ss->id_lock); |
5044 | tmp = idr_get_next(&ss->idr, &tmpid); | 5044 | tmp = idr_get_next(&ss->idr, &tmpid); |
5045 | read_unlock(&ss->id_lock); | 5045 | spin_unlock(&ss->id_lock); |
5046 | 5046 | ||
5047 | if (!tmp) | 5047 | if (!tmp) |
5048 | break; | 5048 | break; |