git://git.onelab.eu
/
linux-2.6.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
vserver 1.9.3
[linux-2.6.git]
/
net
/
ipv6
/
anycast.c
diff --git
a/net/ipv6/anycast.c
b/net/ipv6/anycast.c
index
5b1e4d9
..
a0de548
100644
(file)
--- a/
net/ipv6/anycast.c
+++ b/
net/ipv6/anycast.c
@@
-293,6
+293,7
@@
static void aca_put(struct ifacaddr6 *ac)
{
if (atomic_dec_and_test(&ac->aca_refcnt)) {
in6_dev_put(ac->aca_idev);
{
if (atomic_dec_and_test(&ac->aca_refcnt)) {
in6_dev_put(ac->aca_idev);
+ dst_release(&ac->aca_rt->u.dst);
kfree(ac);
}
}
kfree(ac);
}
}
@@
-304,6
+305,8
@@
int ipv6_dev_ac_inc(struct net_device *dev, struct in6_addr *addr)
{
struct ifacaddr6 *aca;
struct inet6_dev *idev;
{
struct ifacaddr6 *aca;
struct inet6_dev *idev;
+ struct rt6_info *rt;
+ int err;
idev = in6_dev_get(dev);
idev = in6_dev_get(dev);
@@
-312,17
+315,15
@@
int ipv6_dev_ac_inc(struct net_device *dev, struct in6_addr *addr)
write_lock_bh(&idev->lock);
if (idev->dead) {
write_lock_bh(&idev->lock);
if (idev->dead) {
- write_unlock_bh(&idev->lock);
- in6_dev_put(idev);
- return -ENODEV;
+ err = -ENODEV;
+ goto out;
}
for (aca = idev->ac_list; aca; aca = aca->aca_next) {
if (ipv6_addr_cmp(&aca->aca_addr, addr) == 0) {
aca->aca_users++;
}
for (aca = idev->ac_list; aca; aca = aca->aca_next) {
if (ipv6_addr_cmp(&aca->aca_addr, addr) == 0) {
aca->aca_users++;
- write_unlock_bh(&idev->lock);
- in6_dev_put(idev);
- return 0;
+ err = 0;
+ goto out;
}
}
}
}
@@
-333,15
+334,22
@@
int ipv6_dev_ac_inc(struct net_device *dev, struct in6_addr *addr)
aca = kmalloc(sizeof(struct ifacaddr6), GFP_ATOMIC);
if (aca == NULL) {
aca = kmalloc(sizeof(struct ifacaddr6), GFP_ATOMIC);
if (aca == NULL) {
- write_unlock_bh(&idev->lock);
- in6_dev_put(idev);
- return -ENOMEM;
+ err = -ENOMEM;
+ goto out;
+ }
+
+ rt = addrconf_dst_alloc(idev, addr, 1);
+ if (IS_ERR(rt)) {
+ kfree(aca);
+ err = PTR_ERR(rt);
+ goto out;
}
memset(aca, 0, sizeof(struct ifacaddr6));
ipv6_addr_copy(&aca->aca_addr, addr);
aca->aca_idev = idev;
}
memset(aca, 0, sizeof(struct ifacaddr6));
ipv6_addr_copy(&aca->aca_addr, addr);
aca->aca_idev = idev;
+ aca->aca_rt = rt;
aca->aca_users = 1;
/* aca_tstamp should be updated upon changes */
aca->aca_cstamp = aca->aca_tstamp = jiffies;
aca->aca_users = 1;
/* aca_tstamp should be updated upon changes */
aca->aca_cstamp = aca->aca_tstamp = jiffies;
@@
-352,26
+360,27
@@
int ipv6_dev_ac_inc(struct net_device *dev, struct in6_addr *addr)
idev->ac_list = aca;
write_unlock_bh(&idev->lock);
idev->ac_list = aca;
write_unlock_bh(&idev->lock);
- ip6_rt_addr_add(&aca->aca_addr, dev, 1);
+ dst_hold(&rt->u.dst);
+ if (ip6_ins_rt(rt, NULL, NULL))
+ dst_release(&rt->u.dst);
addrconf_join_solict(dev, &aca->aca_addr);
aca_put(aca);
return 0;
addrconf_join_solict(dev, &aca->aca_addr);
aca_put(aca);
return 0;
+out:
+ write_unlock_bh(&idev->lock);
+ in6_dev_put(idev);
+ return err;
}
/*
* device anycast group decrement
*/
}
/*
* device anycast group decrement
*/
-int
ipv6_dev_ac_dec(struct net_device *
dev, struct in6_addr *addr)
+int
__ipv6_dev_ac_dec(struct inet6_dev *i
dev, struct in6_addr *addr)
{
{
- struct inet6_dev *idev;
struct ifacaddr6 *aca, *prev_aca;
struct ifacaddr6 *aca, *prev_aca;
- idev = in6_dev_get(dev);
- if (idev == NULL)
- return -ENODEV;
-
write_lock_bh(&idev->lock);
prev_aca = NULL;
for (aca = idev->ac_list; aca; aca = aca->aca_next) {
write_lock_bh(&idev->lock);
prev_aca = NULL;
for (aca = idev->ac_list; aca; aca = aca->aca_next) {
@@
-381,12
+390,10
@@
int ipv6_dev_ac_dec(struct net_device *dev, struct in6_addr *addr)
}
if (!aca) {
write_unlock_bh(&idev->lock);
}
if (!aca) {
write_unlock_bh(&idev->lock);
- in6_dev_put(idev);
return -ENOENT;
}
if (--aca->aca_users > 0) {
write_unlock_bh(&idev->lock);
return -ENOENT;
}
if (--aca->aca_users > 0) {
write_unlock_bh(&idev->lock);
- in6_dev_put(idev);
return 0;
}
if (prev_aca)
return 0;
}
if (prev_aca)
@@
-394,15
+401,29
@@
int ipv6_dev_ac_dec(struct net_device *dev, struct in6_addr *addr)
else
idev->ac_list = aca->aca_next;
write_unlock_bh(&idev->lock);
else
idev->ac_list = aca->aca_next;
write_unlock_bh(&idev->lock);
- addrconf_leave_solict(dev, &aca->aca_addr);
+ addrconf_leave_solict(
i
dev, &aca->aca_addr);
- ip6_rt_addr_del(&aca->aca_addr, dev);
+ dst_hold(&aca->aca_rt->u.dst);
+ if (ip6_del_rt(aca->aca_rt, NULL, NULL))
+ dst_free(&aca->aca_rt->u.dst);
+ else
+ dst_release(&aca->aca_rt->u.dst);
aca_put(aca);
aca_put(aca);
- in6_dev_put(idev);
return 0;
}
return 0;
}
+int ipv6_dev_ac_dec(struct net_device *dev, struct in6_addr *addr)
+{
+ int ret;
+ struct inet6_dev *idev = in6_dev_get(dev);
+ if (idev == NULL)
+ return -ENODEV;
+ ret = __ipv6_dev_ac_dec(idev, addr);
+ in6_dev_put(idev);
+ return ret;
+}
+
/*
* check if the interface has this anycast address
*/
/*
* check if the interface has this anycast address
*/