diff options
author | Glauber Costa <glommer@parallels.com> | 2011-12-16 04:51:59 +0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-12-17 00:35:17 +0400 |
commit | 36b77a52087a9fca4228c06e0730750f9b6468f0 (patch) | |
tree | 90812a9ce9964e051f5fd286647509560b98ae00 /net/core | |
parent | cb9ffb76949cd7b17c8468f8bf10d0ff75d4cdd2 (diff) | |
download | linux-36b77a52087a9fca4228c06e0730750f9b6468f0.tar.xz |
net: fix sleeping while atomic problem in sock mem_cgroup.
We can't scan the proto_list to initialize sock cgroups, as it
holds a rwlock, and we also want to keep the code generic enough to
avoid calling the initialization functions of protocols directly,
Convert proto_list_lock into a mutex, so we can sleep and do the
necessary allocations. This lock is seldom taken, so there shouldn't
be any performance penalties associated with that
Signed-off-by: Glauber Costa <glommer@parallels.com>
CC: Hiroyouki Kamezawa <kamezawa.hiroyu@jp.fujitsu.com>
CC: David S. Miller <davem@davemloft.net>
CC: Eric Dumazet <eric.dumazet@gmail.com>
CC: Stephen Rothwell <sfr@canb.auug.org.au>
CC: Randy Dunlap <rdunlap@xenotime.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core')
-rw-r--r-- | net/core/sock.c | 28 |
1 files changed, 14 insertions, 14 deletions
diff --git a/net/core/sock.c b/net/core/sock.c index 5a6a90620656..0c67facf42f3 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -136,7 +136,7 @@ #include <net/tcp.h> #endif -static DEFINE_RWLOCK(proto_list_lock); +static DEFINE_MUTEX(proto_list_mutex); static LIST_HEAD(proto_list); #ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM @@ -145,7 +145,7 @@ int mem_cgroup_sockets_init(struct cgroup *cgrp, struct cgroup_subsys *ss) struct proto *proto; int ret = 0; - read_lock(&proto_list_lock); + mutex_lock(&proto_list_mutex); list_for_each_entry(proto, &proto_list, node) { if (proto->init_cgroup) { ret = proto->init_cgroup(cgrp, ss); @@ -154,13 +154,13 @@ int mem_cgroup_sockets_init(struct cgroup *cgrp, struct cgroup_subsys *ss) } } - read_unlock(&proto_list_lock); + mutex_unlock(&proto_list_mutex); return ret; out: list_for_each_entry_continue_reverse(proto, &proto_list, node) if (proto->destroy_cgroup) proto->destroy_cgroup(cgrp, ss); - read_unlock(&proto_list_lock); + mutex_unlock(&proto_list_mutex); return ret; } @@ -168,11 +168,11 @@ void mem_cgroup_sockets_destroy(struct cgroup *cgrp, struct cgroup_subsys *ss) { struct proto *proto; - read_lock(&proto_list_lock); + mutex_lock(&proto_list_mutex); list_for_each_entry_reverse(proto, &proto_list, node) if (proto->destroy_cgroup) proto->destroy_cgroup(cgrp, ss); - read_unlock(&proto_list_lock); + mutex_unlock(&proto_list_mutex); } #endif @@ -2479,10 +2479,10 @@ int proto_register(struct proto *prot, int alloc_slab) } } - write_lock(&proto_list_lock); + mutex_lock(&proto_list_mutex); list_add(&prot->node, &proto_list); assign_proto_idx(prot); - write_unlock(&proto_list_lock); + mutex_unlock(&proto_list_mutex); return 0; out_free_timewait_sock_slab_name: @@ -2505,10 +2505,10 @@ EXPORT_SYMBOL(proto_register); void proto_unregister(struct proto *prot) { - write_lock(&proto_list_lock); + mutex_lock(&proto_list_mutex); release_proto_idx(prot); list_del(&prot->node); - write_unlock(&proto_list_lock); + mutex_unlock(&proto_list_mutex); if (prot->slab != NULL) { kmem_cache_destroy(prot->slab); @@ -2531,9 +2531,9 @@ EXPORT_SYMBOL(proto_unregister); #ifdef CONFIG_PROC_FS static void *proto_seq_start(struct seq_file *seq, loff_t *pos) - __acquires(proto_list_lock) + __acquires(proto_list_mutex) { - read_lock(&proto_list_lock); + mutex_lock(&proto_list_mutex); return seq_list_start_head(&proto_list, *pos); } @@ -2543,9 +2543,9 @@ static void *proto_seq_next(struct seq_file *seq, void *v, loff_t *pos) } static void proto_seq_stop(struct seq_file *seq, void *v) - __releases(proto_list_lock) + __releases(proto_list_mutex) { - read_unlock(&proto_list_lock); + mutex_unlock(&proto_list_mutex); } static char proto_method_implemented(const void *method) |