Commit 84f59370 authored by Denis V. Lunev's avatar Denis V. Lunev Committed by David S. Miller

[IPV6]: Fix refcounting for anycast dst entries.

Anycast DST entries allocated inside ipv6_dev_ac_inc are leaked when
network device is stopped without removing IPv6 addresses from it. The
bug has been observed in the reality on 2.6.18-rhel5 kernel.

In the above case addrconf_ifdown marks all entries as obsolete and
ip6_del_rt called from __ipv6_dev_ac_dec returns ENOENT. The
referrence is not dropped.

The fix is simple. DST entry should not keep referrence when stored in
the FIB6 tree.
Signed-off-by: default avatarDenis V. Lunev <den@openvz.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent eb867579
...@@ -334,9 +334,7 @@ int ipv6_dev_ac_inc(struct net_device *dev, struct in6_addr *addr) ...@@ -334,9 +334,7 @@ int ipv6_dev_ac_inc(struct net_device *dev, struct in6_addr *addr)
idev->ac_list = aca; idev->ac_list = aca;
write_unlock_bh(&idev->lock); write_unlock_bh(&idev->lock);
dst_hold(&rt->u.dst); ip6_ins_rt(rt);
if (ip6_ins_rt(rt))
dst_release(&rt->u.dst);
addrconf_join_solict(dev, &aca->aca_addr); addrconf_join_solict(dev, &aca->aca_addr);
...@@ -378,10 +376,7 @@ int __ipv6_dev_ac_dec(struct inet6_dev *idev, struct in6_addr *addr) ...@@ -378,10 +376,7 @@ int __ipv6_dev_ac_dec(struct inet6_dev *idev, struct in6_addr *addr)
addrconf_leave_solict(idev, &aca->aca_addr); addrconf_leave_solict(idev, &aca->aca_addr);
dst_hold(&aca->aca_rt->u.dst); dst_hold(&aca->aca_rt->u.dst);
if (ip6_del_rt(aca->aca_rt)) ip6_del_rt(aca->aca_rt);
dst_free(&aca->aca_rt->u.dst);
else
dst_release(&aca->aca_rt->u.dst);
aca_put(aca); aca_put(aca);
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment