aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorHugh Dickins <hughd@google.com>2012-03-21 19:34:21 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-03-21 20:55:01 -0400
commit42aee6c495e07dba7410b863a360db6bb9ec6d66 (patch)
treed014b2b5c7aa9d1a1f13686fa06699f9f734ee1c /kernel
parent9f7de8275b46d9d11b1505adbfe6c2bb48df4741 (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.c18
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}
4893EXPORT_SYMBOL_GPL(free_css_id); 4893EXPORT_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;
4932remove_idr: 4932remove_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);
4937err_out: 4937err_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;