aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@vyatta.com>2009-02-26 01:55:31 -0500
committerDavid S. Miller <davem@davemloft.net>2009-03-03 03:47:47 -0500
commitb325fddb7f869e6c95a88dc6573220f162e5b89f (patch)
treeebbde90999700f15e2196edd76351519a2a484b2
parent5a5990d3090b03745a9548a6f5edef02095675cf (diff)
ipv6: Fix sysctl unregistration deadlock
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/ipv6/addrconf.c14
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
496static void addrconf_fixup_forwarding(struct ctl_table *table, int *p, int old) 496static 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
4026static struct addrconf_sysctl_table 4028static struct addrconf_sysctl_table