diff options
author | Stephen Hemminger <shemminger@vyatta.com> | 2009-02-26 01:55:31 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-03-03 03:47:47 -0500 |
commit | b325fddb7f869e6c95a88dc6573220f162e5b89f (patch) | |
tree | ebbde90999700f15e2196edd76351519a2a484b2 /net/ipv6 | |
parent | 5a5990d3090b03745a9548a6f5edef02095675cf (diff) |
ipv6: Fix sysctl unregistration deadlock
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/addrconf.c | 14 |
1 files changed, 8 insertions, 6 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index f9afb452249c..40fabdee42ae 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -493,15 +493,17 @@ static void addrconf_forward_change(struct net *net, __s32 newf) | |||
493 | read_unlock(&dev_base_lock); | 493 | read_unlock(&dev_base_lock); |
494 | } | 494 | } |
495 | 495 | ||
496 | static void addrconf_fixup_forwarding(struct ctl_table *table, int *p, int old) | 496 | static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int old) |
497 | { | 497 | { |
498 | struct net *net; | 498 | struct net *net; |
499 | 499 | ||
500 | net = (struct net *)table->extra2; | 500 | net = (struct net *)table->extra2; |
501 | if (p == &net->ipv6.devconf_dflt->forwarding) | 501 | if (p == &net->ipv6.devconf_dflt->forwarding) |
502 | return; | 502 | return 0; |
503 | |||
504 | if (!rtnl_trylock()) | ||
505 | return -ERESTARTSYS; | ||
503 | 506 | ||
504 | rtnl_lock(); | ||
505 | if (p == &net->ipv6.devconf_all->forwarding) { | 507 | if (p == &net->ipv6.devconf_all->forwarding) { |
506 | __s32 newf = net->ipv6.devconf_all->forwarding; | 508 | __s32 newf = net->ipv6.devconf_all->forwarding; |
507 | net->ipv6.devconf_dflt->forwarding = newf; | 509 | net->ipv6.devconf_dflt->forwarding = newf; |
@@ -512,6 +514,7 @@ static void addrconf_fixup_forwarding(struct ctl_table *table, int *p, int old) | |||
512 | 514 | ||
513 | if (*p) | 515 | if (*p) |
514 | rt6_purge_dflt_routers(net); | 516 | rt6_purge_dflt_routers(net); |
517 | return 1; | ||
515 | } | 518 | } |
516 | #endif | 519 | #endif |
517 | 520 | ||
@@ -3983,7 +3986,7 @@ int addrconf_sysctl_forward(ctl_table *ctl, int write, struct file * filp, | |||
3983 | ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos); | 3986 | ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos); |
3984 | 3987 | ||
3985 | if (write) | 3988 | if (write) |
3986 | addrconf_fixup_forwarding(ctl, valp, val); | 3989 | ret = addrconf_fixup_forwarding(ctl, valp, val); |
3987 | return ret; | 3990 | return ret; |
3988 | } | 3991 | } |
3989 | 3992 | ||
@@ -4019,8 +4022,7 @@ static int addrconf_sysctl_forward_strategy(ctl_table *table, | |||
4019 | } | 4022 | } |
4020 | 4023 | ||
4021 | *valp = new; | 4024 | *valp = new; |
4022 | addrconf_fixup_forwarding(table, valp, val); | 4025 | return addrconf_fixup_forwarding(table, valp, val); |
4023 | return 1; | ||
4024 | } | 4026 | } |
4025 | 4027 | ||
4026 | static struct addrconf_sysctl_table | 4028 | static struct addrconf_sysctl_table |