aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2009-12-03 15:22:55 -0500
committerDavid S. Miller <davem@davemloft.net>2009-12-03 15:22:55 -0500
commite9c5158ac26affd5d8ce006521bdfb7148090e18 (patch)
treea8d43fb446a1908175923f4109c977dcb84e4f91 /net/ipv6
parent3a765edadb28cc736d185f67d1ba6bedcc85f4b9 (diff)
net: Allow fib_rule_unregister to batch
Refactor the code so fib_rules_register always takes a template instead of the actual fib_rules_ops structure that will be used. This is required for network namespace support so 2 out of the 3 callers already do this, it allows the error handling to be made common, and it allows fib_rules_unregister to free the template for hte caller. Modify fib_rules_unregister to use call_rcu instead of syncrhonize_rcu to allw multiple namespaces to be cleaned up in the same rcu grace period. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/fib6_rules.c22
1 files changed, 7 insertions, 15 deletions
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c
index 3b38f49f2c28..b7aa7c64cc4a 100644
--- a/net/ipv6/fib6_rules.c
+++ b/net/ipv6/fib6_rules.c
@@ -264,16 +264,14 @@ static struct fib_rules_ops fib6_rules_ops_template = {
264 264
265static int fib6_rules_net_init(struct net *net) 265static int fib6_rules_net_init(struct net *net)
266{ 266{
267 struct fib_rules_ops *ops;
267 int err = -ENOMEM; 268 int err = -ENOMEM;
268 269
269 net->ipv6.fib6_rules_ops = kmemdup(&fib6_rules_ops_template, 270 ops = fib_rules_register(&fib6_rules_ops_template, net);
270 sizeof(*net->ipv6.fib6_rules_ops), 271 if (IS_ERR(ops))
271 GFP_KERNEL); 272 return PTR_ERR(ops);
272 if (!net->ipv6.fib6_rules_ops) 273 net->ipv6.fib6_rules_ops = ops;
273 goto out;
274 274
275 net->ipv6.fib6_rules_ops->fro_net = net;
276 INIT_LIST_HEAD(&net->ipv6.fib6_rules_ops->rules_list);
277 275
278 err = fib_default_rule_add(net->ipv6.fib6_rules_ops, 0, 276 err = fib_default_rule_add(net->ipv6.fib6_rules_ops, 0,
279 RT6_TABLE_LOCAL, 0); 277 RT6_TABLE_LOCAL, 0);
@@ -283,25 +281,19 @@ static int fib6_rules_net_init(struct net *net)
283 err = fib_default_rule_add(net->ipv6.fib6_rules_ops, 281 err = fib_default_rule_add(net->ipv6.fib6_rules_ops,
284 0x7FFE, RT6_TABLE_MAIN, 0); 282 0x7FFE, RT6_TABLE_MAIN, 0);
285 if (err) 283 if (err)
286 goto out_fib6_default_rule_add; 284 goto out_fib6_rules_ops;
287 285
288 err = fib_rules_register(net->ipv6.fib6_rules_ops);
289 if (err)
290 goto out_fib6_default_rule_add;
291out: 286out:
292 return err; 287 return err;
293 288
294out_fib6_default_rule_add:
295 fib_rules_cleanup_ops(net->ipv6.fib6_rules_ops);
296out_fib6_rules_ops: 289out_fib6_rules_ops:
297 kfree(net->ipv6.fib6_rules_ops); 290 fib_rules_unregister(ops);
298 goto out; 291 goto out;
299} 292}
300 293
301static void fib6_rules_net_exit(struct net *net) 294static void fib6_rules_net_exit(struct net *net)
302{ 295{
303 fib_rules_unregister(net->ipv6.fib6_rules_ops); 296 fib_rules_unregister(net->ipv6.fib6_rules_ops);
304 kfree(net->ipv6.fib6_rules_ops);
305} 297}
306 298
307static struct pernet_operations fib6_rules_net_ops = { 299static struct pernet_operations fib6_rules_net_ops = {