All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH] batman-adv: convert ifmcaddr6 to RCU
@ 2021-04-18 20:14 Linus Lüssing
  2021-04-18 20:16 ` Linus Lüssing
  0 siblings, 1 reply; 4+ messages in thread
From: Linus Lüssing @ 2021-04-18 20:14 UTC (permalink / raw)
  To: b.a.t.m.a.n

From: Taehee Yoo <ap420073@gmail.com>

The ifmcaddr6 has been protected by inet6_dev->lock(rwlock) so that
the critical section is atomic context. In order to switch this context,
changing locking is needed. The ifmcaddr6 actually already protected by
RTNL So if it's converted to use RCU, its control path context can be
switched to sleepable.

Suggested-by: Cong Wang <xiyou.wangcong@gmail.com>
Signed-off-by: Taehee Yoo <ap420073@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
[linus.luessing@c0d3.blue: Add compat code]
Signed-off-by: Linus Lüssing <linus.luessing@c0d3.blue>
---
@Sven: maybe something like this?

Seems to compile fine for me, without warnings and seems to run fine and
use the compat code for me.

I tried to create and add it to compat-include/net/if_inet6.h, as that
would fit better for the "struct ifmcaddr6", but couldn't get that
to work, lots of errors. And when adding it to compat.h the compat code
does not seem to be used at all.

Also let me know if the kernel version is correct or if it should be
5.14 instead?

 compat-include/net/addrconf.h | 85 +++++++++++++++++++++++++++++++++++
 net/batman-adv/multicast.c    |  6 +--
 2 files changed, 88 insertions(+), 3 deletions(-)

diff --git a/compat-include/net/addrconf.h b/compat-include/net/addrconf.h
index 30124124..080e1dda 100644
--- a/compat-include/net/addrconf.h
+++ b/compat-include/net/addrconf.h
@@ -25,4 +25,89 @@ static inline int batadv_ipv6_mc_check_mld(struct sk_buff *skb)
 
 #endif /* LINUX_VERSION_IS_LESS(5, 1, 0) */
 
+#if LINUX_VERSION_IS_LESS(5, 13, 0)
+
+static bool batadv_mcast_mla_is_duplicate(u8 *mcast_addr,
+					  struct hlist_head *mcast_list);
+
+static inline int
+compat_batadv_mcast_mla_softif_get_ipv6(struct net_device *dev,
+				 struct hlist_head *mcast_list,
+				 struct batadv_mcast_mla_flags *flags,
+				 u8 *mcast_addr,
+				struct batadv_hw_addr *new,
+				struct inet6_dev *in6_dev)
+
+{
+	struct ifmcaddr6 *pmc6;
+	int ret = 0;
+
+	if (flags->tvlv_flags & BATADV_MCAST_WANT_ALL_IPV6)
+		return 0;
+
+	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)
+			continue;
+
+		if (flags->tvlv_flags & BATADV_MCAST_WANT_ALL_UNSNOOPABLES &&
+		    ipv6_addr_is_ll_all_nodes(&pmc6->mca_addr))
+			continue;
+
+		if (!(flags->tvlv_flags & BATADV_MCAST_WANT_NO_RTR6) &&
+		    IPV6_ADDR_MC_SCOPE(&pmc6->mca_addr) >
+		    IPV6_ADDR_SCOPE_LINKLOCAL)
+			continue;
+
+		ipv6_eth_mc_map(&pmc6->mca_addr, mcast_addr);
+
+		if (batadv_mcast_mla_is_duplicate(mcast_addr, mcast_list))
+			continue;
+
+		new = kmalloc(sizeof(*new), GFP_ATOMIC);
+		if (!new) {
+			ret = -ENOMEM;
+			break;
+		}
+
+		ether_addr_copy(new->addr, mcast_addr);
+		hlist_add_head(&new->list, mcast_list);
+		ret++;
+	}
+	read_unlock_bh(&in6_dev->lock);
+	rcu_read_unlock();
+
+	return ret;
+}
+
+#define ifmcaddr6 \
+		net_device *orig_dev = dev; \
+		return compat_batadv_mcast_mla_softif_get_ipv6(orig_dev, \
+							       mcast_list, \
+							       flags, \
+							       mcast_addr, \
+							       new = NULL, \
+							       in6_dev = NULL); \
+	} \
+	static inline int \
+	__unused_batadv_mcast_mla_softif_get_ipv6(struct net_device *dev, \
+					     struct hlist_head *mcast_list, \
+					     struct batadv_mcast_mla_flags *flags) \
+	{ \
+		struct batadv_hw_addr *new; \
+		struct inet6_dev *in6_dev; \
+		u8 mcast_addr[ETH_ALEN]; \
+		struct ifmcaddr6
+
+#endif /* LINUX_VERSION_IS_LESS(5, 13, 0) */
+
 #endif	/* _NET_BATMAN_ADV_COMPAT_NET_ADDRCONF_H_ */
diff --git a/net/batman-adv/multicast.c b/net/batman-adv/multicast.c
index 28166402..1d63c8cb 100644
--- a/net/batman-adv/multicast.c
+++ b/net/batman-adv/multicast.c
@@ -454,8 +454,9 @@ batadv_mcast_mla_softif_get_ipv6(struct net_device *dev,
 		return 0;
 	}
 
-	read_lock_bh(&in6_dev->lock);
-	for (pmc6 = in6_dev->mc_list; pmc6; pmc6 = pmc6->next) {
+	for (pmc6 = rcu_dereference(in6_dev->mc_list);
+	     pmc6;
+	     pmc6 = rcu_dereference(pmc6->next)) {
 		if (IPV6_ADDR_MC_SCOPE(&pmc6->mca_addr) <
 		    IPV6_ADDR_SCOPE_LINKLOCAL)
 			continue;
@@ -484,7 +485,6 @@ batadv_mcast_mla_softif_get_ipv6(struct net_device *dev,
 		hlist_add_head(&new->list, mcast_list);
 		ret++;
 	}
-	read_unlock_bh(&in6_dev->lock);
 	rcu_read_unlock();
 
 	return ret;
-- 
2.31.0

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [RFC PATCH] batman-adv: convert ifmcaddr6 to RCU
  2021-04-18 20:14 [RFC PATCH] batman-adv: convert ifmcaddr6 to RCU Linus Lüssing
@ 2021-04-18 20:16 ` Linus Lüssing
  2021-04-18 20:17   ` Linus Lüssing
  0 siblings, 1 reply; 4+ messages in thread
From: Linus Lüssing @ 2021-04-18 20:16 UTC (permalink / raw)
  To: b.a.t.m.a.n

On Sun, Apr 18, 2021 at 10:14:22PM +0200, Linus Lüssing wrote:
> [...]
> diff --git a/net/batman-adv/multicast.c b/net/batman-adv/multicast.c
> index 28166402..1d63c8cb 100644
> --- a/net/batman-adv/multicast.c
> +++ b/net/batman-adv/multicast.c
> @@ -454,8 +454,9 @@ batadv_mcast_mla_softif_get_ipv6(struct net_device *dev,
>  		return 0;
>  	}
>  
> -	read_lock_bh(&in6_dev->lock);
> -	for (pmc6 = in6_dev->mc_list; pmc6; pmc6 = pmc6->next) {
> +	for (pmc6 = rcu_dereference(in6_dev->mc_list);
> +	     pmc6;
> +	     pmc6 = rcu_dereference(pmc6->next)) {
>  		if (IPV6_ADDR_MC_SCOPE(&pmc6->mca_addr) <
>  		    IPV6_ADDR_SCOPE_LINKLOCAL)
>  			continue;
> @@ -484,7 +485,6 @@ batadv_mcast_mla_softif_get_ipv6(struct net_device *dev,
>  		hlist_add_head(&new->list, mcast_list);
>  		ret++;
>  	}
> -	read_unlock_bh(&in6_dev->lock);
>  	rcu_read_unlock();
>  
>  	return ret;
> -- 

Ups, accidentally added this. Will remove that in the next
version.

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [RFC PATCH] batman-adv: convert ifmcaddr6 to RCU
  2021-04-18 20:16 ` Linus Lüssing
@ 2021-04-18 20:17   ` Linus Lüssing
  0 siblings, 0 replies; 4+ messages in thread
From: Linus Lüssing @ 2021-04-18 20:17 UTC (permalink / raw)
  To: b.a.t.m.a.n

On Sun, Apr 18, 2021 at 10:16:07PM +0200, Linus Lüssing wrote:
> On Sun, Apr 18, 2021 at 10:14:22PM +0200, Linus Lüssing wrote:
> > [...]
> > diff --git a/net/batman-adv/multicast.c b/net/batman-adv/multicast.c
> > index 28166402..1d63c8cb 100644
> > --- a/net/batman-adv/multicast.c
> > +++ b/net/batman-adv/multicast.c
> > @@ -454,8 +454,9 @@ batadv_mcast_mla_softif_get_ipv6(struct net_device *dev,
> >  		return 0;
> >  	}
> >  
> > -	read_lock_bh(&in6_dev->lock);
> > -	for (pmc6 = in6_dev->mc_list; pmc6; pmc6 = pmc6->next) {
> > +	for (pmc6 = rcu_dereference(in6_dev->mc_list);
> > +	     pmc6;
> > +	     pmc6 = rcu_dereference(pmc6->next)) {
> >  		if (IPV6_ADDR_MC_SCOPE(&pmc6->mca_addr) <
> >  		    IPV6_ADDR_SCOPE_LINKLOCAL)
> >  			continue;
> > @@ -484,7 +485,6 @@ batadv_mcast_mla_softif_get_ipv6(struct net_device *dev,
> >  		hlist_add_head(&new->list, mcast_list);
> >  		ret++;
> >  	}
> > -	read_unlock_bh(&in6_dev->lock);
> >  	rcu_read_unlock();
> >  
> >  	return ret;
> > -- 
> 
> Ups, accidentally added this. Will remove that in the next
> version.

Ah, no, sorry, should be in there, changed my mind :D.

Sorry for the noise.

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [RFC PATCH] batman-adv: convert ifmcaddr6 to RCU
@ 2021-04-17  7:32 Sven Eckelmann
  0 siblings, 0 replies; 4+ messages in thread
From: Sven Eckelmann @ 2021-04-17  7:32 UTC (permalink / raw)
  To: b.a.t.m.a.n

From: Taehee Yoo <ap420073@gmail.com>

The ifmcaddr6 has been protected by inet6_dev->lock(rwlock) so that
the critical section is atomic context. In order to switch this context,
changing locking is needed. The ifmcaddr6 actually already protected by
RTNL So if it's converted to use RCU, its control path context can be
switched to sleepable.

Suggested-by: Cong Wang <xiyou.wangcong@gmail.com>
Signed-off-by: Taehee Yoo <ap420073@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
This patch is already upstream. But the compat code is missing in
batman-adv. So we have to find a way to call the read_lock_bh/read_unlock_bh
without adding it in multicast.c and not to use rcu_dereference without 
removing it from multicast.c... does anyone have an idea?

 net/batman-adv/multicast.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/net/batman-adv/multicast.c b/net/batman-adv/multicast.c
index 28166402..1d63c8cb 100644
--- a/net/batman-adv/multicast.c
+++ b/net/batman-adv/multicast.c
@@ -454,8 +454,9 @@ batadv_mcast_mla_softif_get_ipv6(struct net_device *dev,
 		return 0;
 	}
 
-	read_lock_bh(&in6_dev->lock);
-	for (pmc6 = in6_dev->mc_list; pmc6; pmc6 = pmc6->next) {
+	for (pmc6 = rcu_dereference(in6_dev->mc_list);
+	     pmc6;
+	     pmc6 = rcu_dereference(pmc6->next)) {
 		if (IPV6_ADDR_MC_SCOPE(&pmc6->mca_addr) <
 		    IPV6_ADDR_SCOPE_LINKLOCAL)
 			continue;
@@ -484,7 +485,6 @@ batadv_mcast_mla_softif_get_ipv6(struct net_device *dev,
 		hlist_add_head(&new->list, mcast_list);
 		ret++;
 	}
-	read_unlock_bh(&in6_dev->lock);
 	rcu_read_unlock();
 
 	return ret;
-- 
2.30.2

^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2021-04-18 20:17 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-04-18 20:14 [RFC PATCH] batman-adv: convert ifmcaddr6 to RCU Linus Lüssing
2021-04-18 20:16 ` Linus Lüssing
2021-04-18 20:17   ` Linus Lüssing
  -- strict thread matches above, loose matches on Subject: below --
2021-04-17  7:32 Sven Eckelmann

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.