diff options
author | Eric W. Biederman <ebiederm@xmission.com> | 2009-12-03 15:22:55 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-12-03 15:22:55 -0500 |
commit | e9c5158ac26affd5d8ce006521bdfb7148090e18 (patch) | |
tree | a8d43fb446a1908175923f4109c977dcb84e4f91 /net/ipv6 | |
parent | 3a765edadb28cc736d185f67d1ba6bedcc85f4b9 (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.c | 22 |
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 | ||
265 | static int fib6_rules_net_init(struct net *net) | 265 | static 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; | ||
291 | out: | 286 | out: |
292 | return err; | 287 | return err; |
293 | 288 | ||
294 | out_fib6_default_rule_add: | ||
295 | fib_rules_cleanup_ops(net->ipv6.fib6_rules_ops); | ||
296 | out_fib6_rules_ops: | 289 | out_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 | ||
301 | static void fib6_rules_net_exit(struct net *net) | 294 | static 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 | ||
307 | static struct pernet_operations fib6_rules_net_ops = { | 299 | static struct pernet_operations fib6_rules_net_ops = { |