batman-adv: Get inet(6) device inside RCU protected region
Commit Message
It is not necessary to get the inet(6)_dev outside of the rcu protected
region by using reference counting. Instead, the in(6)_dev_get can be
replaced by the non-refcnt function and everything can be moved inside the
rcu protected region.
Fixes: 0a7733468f95 ("batman-adv: mcast: detect, distribute and maintain multicast router presence")
Reported-by: David Miller <davem@davemloft.net>
Signed-off-by: Sven Eckelmann <sven@narfation.org>
---
Cc: Linus Lüssing <linus.luessing@c0d3.blue>
net/batman-adv/multicast.c | 22 +++++++++++++---------
1 file changed, 13 insertions(+), 9 deletions(-)
@@ -379,11 +379,14 @@ batadv_mcast_mla_softif_get_ipv4(struct net_device *dev,
if (flags->tvlv_flags & BATADV_MCAST_WANT_ALL_IPV4)
return 0;
- in_dev = in_dev_get(dev);
- if (!in_dev)
+ rcu_read_lock();
+
+ in_dev = __in_dev_get_rcu(dev);
+ if (!in_dev) {
+ rcu_read_unlock();
return 0;
+ }
- rcu_read_lock();
for (pmc = rcu_dereference(in_dev->mc_list); pmc;
pmc = rcu_dereference(pmc->next_rcu)) {
if (flags->tvlv_flags & BATADV_MCAST_WANT_ALL_UNSNOOPABLES &&
@@ -410,7 +413,6 @@ batadv_mcast_mla_softif_get_ipv4(struct net_device *dev,
ret++;
}
rcu_read_unlock();
- in_dev_put(in_dev);
return ret;
}
@@ -444,11 +446,14 @@ batadv_mcast_mla_softif_get_ipv6(struct net_device *dev,
if (flags->tvlv_flags & BATADV_MCAST_WANT_ALL_IPV6)
return 0;
- in6_dev = in6_dev_get(dev);
- if (!in6_dev)
+ rcu_read_lock();
+
+ in6_dev = __in6_dev_get(dev);
+ if (!in6_dev) {
+ rcu_read_unlock();
return 0;
+ }
- read_lock_bh(&in6_dev->lock);
for (pmc6 = in6_dev->mc_list; pmc6; pmc6 = pmc6->next) {
if (IPV6_ADDR_MC_SCOPE(&pmc6->mca_addr) <
IPV6_ADDR_SCOPE_LINKLOCAL)
@@ -478,8 +483,7 @@ batadv_mcast_mla_softif_get_ipv6(struct net_device *dev,
hlist_add_head(&new->list, mcast_list);
ret++;
}
- read_unlock_bh(&in6_dev->lock);
- in6_dev_put(in6_dev);
+ rcu_read_unlock();
return ret;
}