aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/sock.c
diff options
context:
space:
mode:
authorGlauber Costa <glommer@parallels.com>2011-12-15 19:51:59 -0500
committerDavid S. Miller <davem@davemloft.net>2011-12-16 15:35:17 -0500
commit36b77a52087a9fca4228c06e0730750f9b6468f0 (patch)
tree90812a9ce9964e051f5fd286647509560b98ae00 /net/core/sock.c
parentcb9ffb76949cd7b17c8468f8bf10d0ff75d4cdd2 (diff)
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/sock.c')
-rw-r--r--net/core/sock.c28
1 files changed, 14 insertions, 14 deletions
diff --git a/net/core/sock.c b/net/core/sock.c
index 5a6a9062065..0c67facf42f 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -136,7 +136,7 @@
136#include <net/tcp.h> 136#include <net/tcp.h>
137#endif 137#endif
138 138
139static DEFINE_RWLOCK(proto_list_lock); 139static DEFINE_MUTEX(proto_list_mutex);
140static LIST_HEAD(proto_list); 140static LIST_HEAD(proto_list);
141 141
142#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM 142#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM
@@ -145,7 +145,7 @@ int mem_cgroup_sockets_init(struct cgroup *cgrp, struct cgroup_subsys *ss)
145 struct proto *proto; 145 struct proto *proto;
146 int ret = 0; 146 int ret = 0;
147 147
148 read_lock(&proto_list_lock); 148 mutex_lock(&proto_list_mutex);
149 list_for_each_entry(proto, &proto_list, node) { 149 list_for_each_entry(proto, &proto_list, node) {
150 if (proto->init_cgroup) { 150 if (proto->init_cgroup) {
151 ret = proto->init_cgroup(cgrp, ss); 151 ret = proto->init_cgroup(cgrp, ss);
@@ -154,13 +154,13 @@ int mem_cgroup_sockets_init(struct cgroup *cgrp, struct cgroup_subsys *ss)
154 } 154 }
155 } 155 }
156 156
157 read_unlock(&proto_list_lock); 157 mutex_unlock(&proto_list_mutex);
158 return ret; 158 return ret;
159out: 159out:
160 list_for_each_entry_continue_reverse(proto, &proto_list, node) 160 list_for_each_entry_continue_reverse(proto, &proto_list, node)
161 if (proto->destroy_cgroup) 161 if (proto->destroy_cgroup)
162 proto->destroy_cgroup(cgrp, ss); 162 proto->destroy_cgroup(cgrp, ss);
163 read_unlock(&proto_list_lock); 163 mutex_unlock(&proto_list_mutex);
164 return ret; 164 return ret;
165} 165}
166 166
@@ -168,11 +168,11 @@ void mem_cgroup_sockets_destroy(struct cgroup *cgrp, struct cgroup_subsys *ss)
168{ 168{
169 struct proto *proto; 169 struct proto *proto;
170 170
171 read_lock(&proto_list_lock); 171 mutex_lock(&proto_list_mutex);
172 list_for_each_entry_reverse(proto, &proto_list, node) 172 list_for_each_entry_reverse(proto, &proto_list, node)
173 if (proto->destroy_cgroup) 173 if (proto->destroy_cgroup)
174 proto->destroy_cgroup(cgrp, ss); 174 proto->destroy_cgroup(cgrp, ss);
175 read_unlock(&proto_list_lock); 175 mutex_unlock(&proto_list_mutex);
176} 176}
177#endif 177#endif
178 178
@@ -2479,10 +2479,10 @@ int proto_register(struct proto *prot, int alloc_slab)
2479 } 2479 }
2480 } 2480 }
2481 2481
2482 write_lock(&proto_list_lock); 2482 mutex_lock(&proto_list_mutex);
2483 list_add(&prot->node, &proto_list); 2483 list_add(&prot->node, &proto_list);
2484 assign_proto_idx(prot); 2484 assign_proto_idx(prot);
2485 write_unlock(&proto_list_lock); 2485 mutex_unlock(&proto_list_mutex);
2486 return 0; 2486 return 0;
2487 2487
2488out_free_timewait_sock_slab_name: 2488out_free_timewait_sock_slab_name:
@@ -2505,10 +2505,10 @@ EXPORT_SYMBOL(proto_register);
2505 2505
2506void proto_unregister(struct proto *prot) 2506void proto_unregister(struct proto *prot)
2507{ 2507{
2508 write_lock(&proto_list_lock); 2508 mutex_lock(&proto_list_mutex);
2509 release_proto_idx(prot); 2509 release_proto_idx(prot);
2510 list_del(&prot->node); 2510 list_del(&prot->node);
2511 write_unlock(&proto_list_lock); 2511 mutex_unlock(&proto_list_mutex);
2512 2512
2513 if (prot->slab != NULL) { 2513 if (prot->slab != NULL) {
2514 kmem_cache_destroy(prot->slab); 2514 kmem_cache_destroy(prot->slab);
@@ -2531,9 +2531,9 @@ EXPORT_SYMBOL(proto_unregister);
2531 2531
2532#ifdef CONFIG_PROC_FS 2532#ifdef CONFIG_PROC_FS
2533static void *proto_seq_start(struct seq_file *seq, loff_t *pos) 2533static void *proto_seq_start(struct seq_file *seq, loff_t *pos)
2534 __acquires(proto_list_lock) 2534 __acquires(proto_list_mutex)
2535{ 2535{
2536 read_lock(&proto_list_lock); 2536 mutex_lock(&proto_list_mutex);
2537 return seq_list_start_head(&proto_list, *pos); 2537 return seq_list_start_head(&proto_list, *pos);
2538} 2538}
2539 2539
@@ -2543,9 +2543,9 @@ static void *proto_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2543} 2543}
2544 2544
2545static void proto_seq_stop(struct seq_file *seq, void *v) 2545static void proto_seq_stop(struct seq_file *seq, void *v)
2546 __releases(proto_list_lock) 2546 __releases(proto_list_mutex)
2547{ 2547{
2548 read_unlock(&proto_list_lock); 2548 mutex_unlock(&proto_list_mutex);
2549} 2549}
2550 2550
2551static char proto_method_implemented(const void *method) 2551static char proto_method_implemented(const void *method)