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>
This commit is contained in:
Eric W. Biederman
2009-12-03 12:22:55 -08:00
committed by David S. Miller
parent 3a765edadb
commit e9c5158ac2
5 changed files with 57 additions and 38 deletions

View File

@@ -264,16 +264,14 @@ static struct fib_rules_ops fib6_rules_ops_template = {
static int fib6_rules_net_init(struct net *net)
{
struct fib_rules_ops *ops;
int err = -ENOMEM;
net->ipv6.fib6_rules_ops = kmemdup(&fib6_rules_ops_template,
sizeof(*net->ipv6.fib6_rules_ops),
GFP_KERNEL);
if (!net->ipv6.fib6_rules_ops)
goto out;
ops = fib_rules_register(&fib6_rules_ops_template, net);
if (IS_ERR(ops))
return PTR_ERR(ops);
net->ipv6.fib6_rules_ops = ops;
net->ipv6.fib6_rules_ops->fro_net = net;
INIT_LIST_HEAD(&net->ipv6.fib6_rules_ops->rules_list);
err = fib_default_rule_add(net->ipv6.fib6_rules_ops, 0,
RT6_TABLE_LOCAL, 0);
@@ -283,25 +281,19 @@ static int fib6_rules_net_init(struct net *net)
err = fib_default_rule_add(net->ipv6.fib6_rules_ops,
0x7FFE, RT6_TABLE_MAIN, 0);
if (err)
goto out_fib6_default_rule_add;
goto out_fib6_rules_ops;
err = fib_rules_register(net->ipv6.fib6_rules_ops);
if (err)
goto out_fib6_default_rule_add;
out:
return err;
out_fib6_default_rule_add:
fib_rules_cleanup_ops(net->ipv6.fib6_rules_ops);
out_fib6_rules_ops:
kfree(net->ipv6.fib6_rules_ops);
fib_rules_unregister(ops);
goto out;
}
static void fib6_rules_net_exit(struct net *net)
{
fib_rules_unregister(net->ipv6.fib6_rules_ops);
kfree(net->ipv6.fib6_rules_ops);
}
static struct pernet_operations fib6_rules_net_ops = {