aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2007-03-14 19:37:52 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-04-26 01:25:39 -0400
commitb19caa0ca071dce76b0e81e957e7eb7c03d72cf5 (patch)
treebaf307a4daa2c63ccc451d6dbcd47f55945aea9a /net
parent587aa64163bb14f70098f450abab9410787fce9d (diff)
[NETFILTER]: nf_conntrack: switch protocol registration/unregistration to mutex
The protocol lookups done by nf_conntrack are already protected by RCU, there is no need to keep taking nf_conntrack_lock for registration and unregistration. Switch to a mutex. Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/netfilter/nf_conntrack_proto.c52
1 files changed, 23 insertions, 29 deletions
diff --git a/net/netfilter/nf_conntrack_proto.c b/net/netfilter/nf_conntrack_proto.c
index 456155f05c75..e2c4a58603a8 100644
--- a/net/netfilter/nf_conntrack_proto.c
+++ b/net/netfilter/nf_conntrack_proto.c
@@ -32,9 +32,9 @@ struct nf_conntrack_l4proto **nf_ct_protos[PF_MAX] __read_mostly;
32struct nf_conntrack_l3proto *nf_ct_l3protos[AF_MAX] __read_mostly; 32struct nf_conntrack_l3proto *nf_ct_l3protos[AF_MAX] __read_mostly;
33EXPORT_SYMBOL_GPL(nf_ct_l3protos); 33EXPORT_SYMBOL_GPL(nf_ct_l3protos);
34 34
35#ifdef CONFIG_SYSCTL 35static DEFINE_MUTEX(nf_ct_proto_mutex);
36static DEFINE_MUTEX(nf_ct_proto_sysctl_mutex);
37 36
37#ifdef CONFIG_SYSCTL
38static int 38static int
39nf_ct_register_sysctl(struct ctl_table_header **header, struct ctl_table *path, 39nf_ct_register_sysctl(struct ctl_table_header **header, struct ctl_table *path,
40 struct ctl_table *table, unsigned int *users) 40 struct ctl_table *table, unsigned int *users)
@@ -164,13 +164,13 @@ static int nf_ct_l3proto_register_sysctl(struct nf_conntrack_l3proto *l3proto)
164 int err = 0; 164 int err = 0;
165 165
166#ifdef CONFIG_SYSCTL 166#ifdef CONFIG_SYSCTL
167 mutex_lock(&nf_ct_proto_sysctl_mutex); 167 mutex_lock(&nf_ct_proto_mutex);
168 if (l3proto->ctl_table != NULL) { 168 if (l3proto->ctl_table != NULL) {
169 err = nf_ct_register_sysctl(&l3proto->ctl_table_header, 169 err = nf_ct_register_sysctl(&l3proto->ctl_table_header,
170 l3proto->ctl_table_path, 170 l3proto->ctl_table_path,
171 l3proto->ctl_table, NULL); 171 l3proto->ctl_table, NULL);
172 } 172 }
173 mutex_unlock(&nf_ct_proto_sysctl_mutex); 173 mutex_unlock(&nf_ct_proto_mutex);
174#endif 174#endif
175 return err; 175 return err;
176} 176}
@@ -178,11 +178,11 @@ static int nf_ct_l3proto_register_sysctl(struct nf_conntrack_l3proto *l3proto)
178static void nf_ct_l3proto_unregister_sysctl(struct nf_conntrack_l3proto *l3proto) 178static void nf_ct_l3proto_unregister_sysctl(struct nf_conntrack_l3proto *l3proto)
179{ 179{
180#ifdef CONFIG_SYSCTL 180#ifdef CONFIG_SYSCTL
181 mutex_lock(&nf_ct_proto_sysctl_mutex); 181 mutex_lock(&nf_ct_proto_mutex);
182 if (l3proto->ctl_table_header != NULL) 182 if (l3proto->ctl_table_header != NULL)
183 nf_ct_unregister_sysctl(&l3proto->ctl_table_header, 183 nf_ct_unregister_sysctl(&l3proto->ctl_table_header,
184 l3proto->ctl_table, NULL); 184 l3proto->ctl_table, NULL);
185 mutex_unlock(&nf_ct_proto_sysctl_mutex); 185 mutex_unlock(&nf_ct_proto_mutex);
186#endif 186#endif
187} 187}
188 188
@@ -195,13 +195,13 @@ int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto)
195 goto out; 195 goto out;
196 } 196 }
197 197
198 write_lock_bh(&nf_conntrack_lock); 198 mutex_lock(&nf_ct_proto_mutex);
199 if (nf_ct_l3protos[proto->l3proto] != &nf_conntrack_l3proto_generic) { 199 if (nf_ct_l3protos[proto->l3proto] != &nf_conntrack_l3proto_generic) {
200 ret = -EBUSY; 200 ret = -EBUSY;
201 goto out_unlock; 201 goto out_unlock;
202 } 202 }
203 rcu_assign_pointer(nf_ct_l3protos[proto->l3proto], proto); 203 rcu_assign_pointer(nf_ct_l3protos[proto->l3proto], proto);
204 write_unlock_bh(&nf_conntrack_lock); 204 mutex_unlock(&nf_ct_proto_mutex);
205 205
206 ret = nf_ct_l3proto_register_sysctl(proto); 206 ret = nf_ct_l3proto_register_sysctl(proto);
207 if (ret < 0) 207 if (ret < 0)
@@ -209,7 +209,7 @@ int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto)
209 return ret; 209 return ret;
210 210
211out_unlock: 211out_unlock:
212 write_unlock_bh(&nf_conntrack_lock); 212 mutex_unlock(&nf_ct_proto_mutex);
213out: 213out:
214 return ret; 214 return ret;
215} 215}
@@ -219,11 +219,11 @@ void nf_conntrack_l3proto_unregister(struct nf_conntrack_l3proto *proto)
219{ 219{
220 BUG_ON(proto->l3proto >= AF_MAX); 220 BUG_ON(proto->l3proto >= AF_MAX);
221 221
222 write_lock_bh(&nf_conntrack_lock); 222 mutex_lock(&nf_ct_proto_mutex);
223 BUG_ON(nf_ct_l3protos[proto->l3proto] != proto); 223 BUG_ON(nf_ct_l3protos[proto->l3proto] != proto);
224 rcu_assign_pointer(nf_ct_l3protos[proto->l3proto], 224 rcu_assign_pointer(nf_ct_l3protos[proto->l3proto],
225 &nf_conntrack_l3proto_generic); 225 &nf_conntrack_l3proto_generic);
226 write_unlock_bh(&nf_conntrack_lock); 226 mutex_unlock(&nf_ct_proto_mutex);
227 synchronize_rcu(); 227 synchronize_rcu();
228 228
229 nf_ct_l3proto_unregister_sysctl(proto); 229 nf_ct_l3proto_unregister_sysctl(proto);
@@ -238,7 +238,7 @@ static int nf_ct_l4proto_register_sysctl(struct nf_conntrack_l4proto *l4proto)
238 int err = 0; 238 int err = 0;
239 239
240#ifdef CONFIG_SYSCTL 240#ifdef CONFIG_SYSCTL
241 mutex_lock(&nf_ct_proto_sysctl_mutex); 241 mutex_lock(&nf_ct_proto_mutex);
242 if (l4proto->ctl_table != NULL) { 242 if (l4proto->ctl_table != NULL) {
243 err = nf_ct_register_sysctl(l4proto->ctl_table_header, 243 err = nf_ct_register_sysctl(l4proto->ctl_table_header,
244 nf_net_netfilter_sysctl_path, 244 nf_net_netfilter_sysctl_path,
@@ -260,7 +260,7 @@ static int nf_ct_l4proto_register_sysctl(struct nf_conntrack_l4proto *l4proto)
260 } 260 }
261#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ 261#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */
262out: 262out:
263 mutex_unlock(&nf_ct_proto_sysctl_mutex); 263 mutex_unlock(&nf_ct_proto_mutex);
264#endif /* CONFIG_SYSCTL */ 264#endif /* CONFIG_SYSCTL */
265 return err; 265 return err;
266} 266}
@@ -268,7 +268,7 @@ out:
268static void nf_ct_l4proto_unregister_sysctl(struct nf_conntrack_l4proto *l4proto) 268static void nf_ct_l4proto_unregister_sysctl(struct nf_conntrack_l4proto *l4proto)
269{ 269{
270#ifdef CONFIG_SYSCTL 270#ifdef CONFIG_SYSCTL
271 mutex_lock(&nf_ct_proto_sysctl_mutex); 271 mutex_lock(&nf_ct_proto_mutex);
272 if (l4proto->ctl_table_header != NULL && 272 if (l4proto->ctl_table_header != NULL &&
273 *l4proto->ctl_table_header != NULL) 273 *l4proto->ctl_table_header != NULL)
274 nf_ct_unregister_sysctl(l4proto->ctl_table_header, 274 nf_ct_unregister_sysctl(l4proto->ctl_table_header,
@@ -279,7 +279,7 @@ static void nf_ct_l4proto_unregister_sysctl(struct nf_conntrack_l4proto *l4proto
279 nf_ct_unregister_sysctl(&l4proto->ctl_compat_table_header, 279 nf_ct_unregister_sysctl(&l4proto->ctl_compat_table_header,
280 l4proto->ctl_compat_table, NULL); 280 l4proto->ctl_compat_table, NULL);
281#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ 281#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */
282 mutex_unlock(&nf_ct_proto_sysctl_mutex); 282 mutex_unlock(&nf_ct_proto_mutex);
283#endif /* CONFIG_SYSCTL */ 283#endif /* CONFIG_SYSCTL */
284} 284}
285 285
@@ -297,8 +297,8 @@ int nf_conntrack_l4proto_register(struct nf_conntrack_l4proto *l4proto)
297 if (l4proto == &nf_conntrack_l4proto_generic) 297 if (l4proto == &nf_conntrack_l4proto_generic)
298 return nf_ct_l4proto_register_sysctl(l4proto); 298 return nf_ct_l4proto_register_sysctl(l4proto);
299 299
300 mutex_lock(&nf_ct_proto_mutex);
300retry: 301retry:
301 write_lock_bh(&nf_conntrack_lock);
302 if (nf_ct_protos[l4proto->l3proto]) { 302 if (nf_ct_protos[l4proto->l3proto]) {
303 if (nf_ct_protos[l4proto->l3proto][l4proto->l4proto] 303 if (nf_ct_protos[l4proto->l3proto][l4proto->l4proto]
304 != &nf_conntrack_l4proto_generic) { 304 != &nf_conntrack_l4proto_generic) {
@@ -310,28 +310,22 @@ retry:
310 struct nf_conntrack_l4proto **proto_array; 310 struct nf_conntrack_l4proto **proto_array;
311 int i; 311 int i;
312 312
313 write_unlock_bh(&nf_conntrack_lock);
314
315 proto_array = (struct nf_conntrack_l4proto **) 313 proto_array = (struct nf_conntrack_l4proto **)
316 kmalloc(MAX_NF_CT_PROTO * 314 kmalloc(MAX_NF_CT_PROTO *
317 sizeof(struct nf_conntrack_l4proto *), 315 sizeof(struct nf_conntrack_l4proto *),
318 GFP_KERNEL); 316 GFP_KERNEL);
319 if (proto_array == NULL) { 317 if (proto_array == NULL) {
320 ret = -ENOMEM; 318 ret = -ENOMEM;
321 goto out; 319 goto out_unlock;
322 } 320 }
323 for (i = 0; i < MAX_NF_CT_PROTO; i++) 321 for (i = 0; i < MAX_NF_CT_PROTO; i++)
324 proto_array[i] = &nf_conntrack_l4proto_generic; 322 proto_array[i] = &nf_conntrack_l4proto_generic;
325 323
326 write_lock_bh(&nf_conntrack_lock); 324 if (nf_ct_protos[l4proto->l3proto])
327 if (nf_ct_protos[l4proto->l3proto]) {
328 /* bad timing, but no problem */ 325 /* bad timing, but no problem */
329 write_unlock_bh(&nf_conntrack_lock);
330 kfree(proto_array); 326 kfree(proto_array);
331 } else { 327 else
332 nf_ct_protos[l4proto->l3proto] = proto_array; 328 nf_ct_protos[l4proto->l3proto] = proto_array;
333 write_unlock_bh(&nf_conntrack_lock);
334 }
335 329
336 /* 330 /*
337 * Just once because array is never freed until unloading 331 * Just once because array is never freed until unloading
@@ -341,7 +335,7 @@ retry:
341 } 335 }
342 336
343 rcu_assign_pointer(nf_ct_protos[l4proto->l3proto][l4proto->l4proto], l4proto); 337 rcu_assign_pointer(nf_ct_protos[l4proto->l3proto][l4proto->l4proto], l4proto);
344 write_unlock_bh(&nf_conntrack_lock); 338 mutex_unlock(&nf_ct_proto_mutex);
345 339
346 ret = nf_ct_l4proto_register_sysctl(l4proto); 340 ret = nf_ct_l4proto_register_sysctl(l4proto);
347 if (ret < 0) 341 if (ret < 0)
@@ -349,7 +343,7 @@ retry:
349 return ret; 343 return ret;
350 344
351out_unlock: 345out_unlock:
352 write_unlock_bh(&nf_conntrack_lock); 346 mutex_unlock(&nf_ct_proto_mutex);
353out: 347out:
354 return ret; 348 return ret;
355} 349}
@@ -364,11 +358,11 @@ void nf_conntrack_l4proto_unregister(struct nf_conntrack_l4proto *l4proto)
364 return; 358 return;
365 } 359 }
366 360
367 write_lock_bh(&nf_conntrack_lock); 361 mutex_lock(&nf_ct_proto_mutex);
368 BUG_ON(nf_ct_protos[l4proto->l3proto][l4proto->l4proto] != l4proto); 362 BUG_ON(nf_ct_protos[l4proto->l3proto][l4proto->l4proto] != l4proto);
369 rcu_assign_pointer(nf_ct_protos[l4proto->l3proto][l4proto->l4proto], 363 rcu_assign_pointer(nf_ct_protos[l4proto->l3proto][l4proto->l4proto],
370 &nf_conntrack_l4proto_generic); 364 &nf_conntrack_l4proto_generic);
371 write_unlock_bh(&nf_conntrack_lock); 365 mutex_unlock(&nf_ct_proto_mutex);
372 synchronize_rcu(); 366 synchronize_rcu();
373 367
374 nf_ct_l4proto_unregister_sysctl(l4proto); 368 nf_ct_l4proto_unregister_sysctl(l4proto);