diff options
author | Glauber Costa <glommer@parallels.com> | 2011-12-15 19:51:59 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-12-16 15:35:17 -0500 |
commit | 36b77a52087a9fca4228c06e0730750f9b6468f0 (patch) | |
tree | 90812a9ce9964e051f5fd286647509560b98ae00 /net/core/sock.c | |
parent | cb9ffb76949cd7b17c8468f8bf10d0ff75d4cdd2 (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.c | 28 |
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 | ||
139 | static DEFINE_RWLOCK(proto_list_lock); | 139 | static DEFINE_MUTEX(proto_list_mutex); |
140 | static LIST_HEAD(proto_list); | 140 | static 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; |
159 | out: | 159 | out: |
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 | ||
2488 | out_free_timewait_sock_slab_name: | 2488 | out_free_timewait_sock_slab_name: |
@@ -2505,10 +2505,10 @@ EXPORT_SYMBOL(proto_register); | |||
2505 | 2505 | ||
2506 | void proto_unregister(struct proto *prot) | 2506 | void 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 |
2533 | static void *proto_seq_start(struct seq_file *seq, loff_t *pos) | 2533 | static 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 | ||
2545 | static void proto_seq_stop(struct seq_file *seq, void *v) | 2545 | static 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 | ||
2551 | static char proto_method_implemented(const void *method) | 2551 | static char proto_method_implemented(const void *method) |