netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [Patch net-next 0/5] ipv6: clean up locking in anycast and mcast
@ 2014-09-09 23:52 Cong Wang
  2014-09-09 23:52 ` [Patch net-next 1/5] ipv6: drop useless rcu_read_lock() in anycast Cong Wang
                   ` (5 more replies)
  0 siblings, 6 replies; 12+ messages in thread
From: Cong Wang @ 2014-09-09 23:52 UTC (permalink / raw)
  To: netdev; +Cc: Hannes Frederic Sowa, Hideaki YOSHIFUJI, David S. Miller,
	Cong Wang

This patchset cleans up the locking in anycast.c and mcast.c.

Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>

Cong Wang (5):
  ipv6: drop useless rcu_read_lock() in anycast
  ipv6: remove ipv6_sk_ac_lock
  ipv6: clean up ipv6_dev_ac_inc()
  ipv6: drop ipv6_sk_mc_lock in mcast
  ipv6: drop some rcu_read_lock in mcast

 include/linux/netdevice.h |  4 ++--
 include/net/addrconf.h    |  2 +-
 net/core/dev.c            | 14 +++++++------
 net/ipv6/addrconf.c       |  2 +-
 net/ipv6/anycast.c        | 52 +++++++++++++----------------------------------
 net/ipv6/mcast.c          | 35 ++++++-------------------------
 6 files changed, 32 insertions(+), 77 deletions(-)

-- 
1.8.3.1

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

* [Patch net-next 1/5] ipv6: drop useless rcu_read_lock() in anycast
  2014-09-09 23:52 [Patch net-next 0/5] ipv6: clean up locking in anycast and mcast Cong Wang
@ 2014-09-09 23:52 ` Cong Wang
  2014-09-09 23:52 ` [Patch net-next 2/5] ipv6: remove ipv6_sk_ac_lock Cong Wang
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 12+ messages in thread
From: Cong Wang @ 2014-09-09 23:52 UTC (permalink / raw)
  To: netdev; +Cc: Hannes Frederic Sowa, Hideaki YOSHIFUJI, David S. Miller,
	Cong Wang

These code is now protected by rtnl lock, rcu read lock
is useless now.

Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
---
 include/linux/netdevice.h |  4 ++--
 net/core/dev.c            | 14 ++++++++------
 net/ipv6/anycast.c        | 18 ++++++------------
 3 files changed, 16 insertions(+), 20 deletions(-)

diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index ba72f6b..17e640a 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -2083,8 +2083,8 @@ void __dev_remove_pack(struct packet_type *pt);
 void dev_add_offload(struct packet_offload *po);
 void dev_remove_offload(struct packet_offload *po);
 
-struct net_device *dev_get_by_flags_rcu(struct net *net, unsigned short flags,
-					unsigned short mask);
+struct net_device *__dev_get_by_flags(struct net *net, unsigned short flags,
+				      unsigned short mask);
 struct net_device *dev_get_by_name(struct net *net, const char *name);
 struct net_device *dev_get_by_name_rcu(struct net *net, const char *name);
 struct net_device *__dev_get_by_name(struct net *net, const char *name);
diff --git a/net/core/dev.c b/net/core/dev.c
index 3c6a967..2595f07 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -897,23 +897,25 @@ struct net_device *dev_getfirstbyhwtype(struct net *net, unsigned short type)
 EXPORT_SYMBOL(dev_getfirstbyhwtype);
 
 /**
- *	dev_get_by_flags_rcu - find any device with given flags
+ *	__dev_get_by_flags - find any device with given flags
  *	@net: the applicable net namespace
  *	@if_flags: IFF_* values
  *	@mask: bitmask of bits in if_flags to check
  *
  *	Search for any interface with the given flags. Returns NULL if a device
  *	is not found or a pointer to the device. Must be called inside
- *	rcu_read_lock(), and result refcount is unchanged.
+ *	rtnl_lock(), and result refcount is unchanged.
  */
 
-struct net_device *dev_get_by_flags_rcu(struct net *net, unsigned short if_flags,
-				    unsigned short mask)
+struct net_device *__dev_get_by_flags(struct net *net, unsigned short if_flags,
+				      unsigned short mask)
 {
 	struct net_device *dev, *ret;
 
+	ASSERT_RTNL();
+
 	ret = NULL;
-	for_each_netdev_rcu(net, dev) {
+	for_each_netdev(net, dev) {
 		if (((dev->flags ^ if_flags) & mask) == 0) {
 			ret = dev;
 			break;
@@ -921,7 +923,7 @@ struct net_device *dev_get_by_flags_rcu(struct net *net, unsigned short if_flags
 	}
 	return ret;
 }
-EXPORT_SYMBOL(dev_get_by_flags_rcu);
+EXPORT_SYMBOL(__dev_get_by_flags);
 
 /**
  *	dev_valid_name - check if name is okay for network device
diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c
index ff2de7d..3b0429b 100644
--- a/net/ipv6/anycast.c
+++ b/net/ipv6/anycast.c
@@ -78,7 +78,6 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, const struct in6_addr *addr)
 	pac->acl_addr = *addr;
 
 	rtnl_lock();
-	rcu_read_lock();
 	if (ifindex == 0) {
 		struct rt6_info *rt;
 
@@ -91,11 +90,11 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, const struct in6_addr *addr)
 			goto error;
 		} else {
 			/* router, no matching interface: just pick one */
-			dev = dev_get_by_flags_rcu(net, IFF_UP,
-						   IFF_UP | IFF_LOOPBACK);
+			dev = __dev_get_by_flags(net, IFF_UP,
+						 IFF_UP | IFF_LOOPBACK);
 		}
 	} else
-		dev = dev_get_by_index_rcu(net, ifindex);
+		dev = __dev_get_by_index(net, ifindex);
 
 	if (dev == NULL) {
 		err = -ENODEV;
@@ -137,7 +136,6 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, const struct in6_addr *addr)
 	}
 
 error:
-	rcu_read_unlock();
 	rtnl_unlock();
 	if (pac)
 		sock_kfree_s(sk, pac, sizeof(*pac));
@@ -174,11 +172,9 @@ int ipv6_sock_ac_drop(struct sock *sk, int ifindex, const struct in6_addr *addr)
 	spin_unlock_bh(&ipv6_sk_ac_lock);
 
 	rtnl_lock();
-	rcu_read_lock();
-	dev = dev_get_by_index_rcu(net, pac->acl_ifindex);
+	dev = __dev_get_by_index(net, pac->acl_ifindex);
 	if (dev)
 		ipv6_dev_ac_dec(dev, &pac->acl_addr);
-	rcu_read_unlock();
 	rtnl_unlock();
 
 	sock_kfree_s(sk, pac, sizeof(*pac));
@@ -203,12 +199,11 @@ void ipv6_sock_ac_close(struct sock *sk)
 
 	prev_index = 0;
 	rtnl_lock();
-	rcu_read_lock();
 	while (pac) {
 		struct ipv6_ac_socklist *next = pac->acl_next;
 
 		if (pac->acl_ifindex != prev_index) {
-			dev = dev_get_by_index_rcu(net, pac->acl_ifindex);
+			dev = __dev_get_by_index(net, pac->acl_ifindex);
 			prev_index = pac->acl_ifindex;
 		}
 		if (dev)
@@ -216,7 +211,6 @@ void ipv6_sock_ac_close(struct sock *sk)
 		sock_kfree_s(sk, pac, sizeof(*pac));
 		pac = next;
 	}
-	rcu_read_unlock();
 	rtnl_unlock();
 }
 
@@ -341,7 +335,7 @@ int __ipv6_dev_ac_dec(struct inet6_dev *idev, const struct in6_addr *addr)
 	return 0;
 }
 
-/* called with rcu_read_lock() */
+/* called with rtnl_lock() */
 static int ipv6_dev_ac_dec(struct net_device *dev, const struct in6_addr *addr)
 {
 	struct inet6_dev *idev = __in6_dev_get(dev);
-- 
1.8.3.1

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

* [Patch net-next 2/5] ipv6: remove ipv6_sk_ac_lock
  2014-09-09 23:52 [Patch net-next 0/5] ipv6: clean up locking in anycast and mcast Cong Wang
  2014-09-09 23:52 ` [Patch net-next 1/5] ipv6: drop useless rcu_read_lock() in anycast Cong Wang
@ 2014-09-09 23:52 ` Cong Wang
  2014-09-09 23:52 ` [Patch net-next 3/5] ipv6: clean up ipv6_dev_ac_inc() Cong Wang
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 12+ messages in thread
From: Cong Wang @ 2014-09-09 23:52 UTC (permalink / raw)
  To: netdev; +Cc: Hannes Frederic Sowa, Hideaki YOSHIFUJI, David S. Miller,
	Cong Wang

Just move rtnl lock up, so that the anycast list can be protected
by rtnl lock now.

Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
---
 net/ipv6/anycast.c | 17 +++--------------
 1 file changed, 3 insertions(+), 14 deletions(-)

diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c
index 3b0429b..d10f2e2 100644
--- a/net/ipv6/anycast.c
+++ b/net/ipv6/anycast.c
@@ -46,10 +46,6 @@
 
 static int ipv6_dev_ac_dec(struct net_device *dev, const struct in6_addr *addr);
 
-/* Big ac list lock for all the sockets */
-static DEFINE_SPINLOCK(ipv6_sk_ac_lock);
-
-
 /*
  *	socket join an anycast group
  */
@@ -128,10 +124,8 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, const struct in6_addr *addr)
 
 	err = ipv6_dev_ac_inc(dev, addr);
 	if (!err) {
-		spin_lock_bh(&ipv6_sk_ac_lock);
 		pac->acl_next = np->ipv6_ac_list;
 		np->ipv6_ac_list = pac;
-		spin_unlock_bh(&ipv6_sk_ac_lock);
 		pac = NULL;
 	}
 
@@ -152,7 +146,7 @@ int ipv6_sock_ac_drop(struct sock *sk, int ifindex, const struct in6_addr *addr)
 	struct ipv6_ac_socklist *pac, *prev_pac;
 	struct net *net = sock_net(sk);
 
-	spin_lock_bh(&ipv6_sk_ac_lock);
+	rtnl_lock();
 	prev_pac = NULL;
 	for (pac = np->ipv6_ac_list; pac; pac = pac->acl_next) {
 		if ((ifindex == 0 || pac->acl_ifindex == ifindex) &&
@@ -161,7 +155,7 @@ int ipv6_sock_ac_drop(struct sock *sk, int ifindex, const struct in6_addr *addr)
 		prev_pac = pac;
 	}
 	if (!pac) {
-		spin_unlock_bh(&ipv6_sk_ac_lock);
+		rtnl_unlock();
 		return -ENOENT;
 	}
 	if (prev_pac)
@@ -169,9 +163,6 @@ int ipv6_sock_ac_drop(struct sock *sk, int ifindex, const struct in6_addr *addr)
 	else
 		np->ipv6_ac_list = pac->acl_next;
 
-	spin_unlock_bh(&ipv6_sk_ac_lock);
-
-	rtnl_lock();
 	dev = __dev_get_by_index(net, pac->acl_ifindex);
 	if (dev)
 		ipv6_dev_ac_dec(dev, &pac->acl_addr);
@@ -192,13 +183,11 @@ void ipv6_sock_ac_close(struct sock *sk)
 	if (!np->ipv6_ac_list)
 		return;
 
-	spin_lock_bh(&ipv6_sk_ac_lock);
+	rtnl_lock();
 	pac = np->ipv6_ac_list;
 	np->ipv6_ac_list = NULL;
-	spin_unlock_bh(&ipv6_sk_ac_lock);
 
 	prev_index = 0;
-	rtnl_lock();
 	while (pac) {
 		struct ipv6_ac_socklist *next = pac->acl_next;
 
-- 
1.8.3.1

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

* [Patch net-next 3/5] ipv6: clean up ipv6_dev_ac_inc()
  2014-09-09 23:52 [Patch net-next 0/5] ipv6: clean up locking in anycast and mcast Cong Wang
  2014-09-09 23:52 ` [Patch net-next 1/5] ipv6: drop useless rcu_read_lock() in anycast Cong Wang
  2014-09-09 23:52 ` [Patch net-next 2/5] ipv6: remove ipv6_sk_ac_lock Cong Wang
@ 2014-09-09 23:52 ` Cong Wang
  2014-09-10 12:23   ` Hannes Frederic Sowa
  2014-09-09 23:52 ` [Patch net-next 4/5] ipv6: drop ipv6_sk_mc_lock in mcast Cong Wang
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 12+ messages in thread
From: Cong Wang @ 2014-09-09 23:52 UTC (permalink / raw)
  To: netdev; +Cc: Hannes Frederic Sowa, Hideaki YOSHIFUJI, David S. Miller,
	Cong Wang

Make it accept inet6_dev, and rename it to __ipv6_dev_ac_inc()
to reflect this change.

Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
---
 include/net/addrconf.h |  2 +-
 net/ipv6/addrconf.c    |  2 +-
 net/ipv6/anycast.c     | 17 +++++------------
 3 files changed, 7 insertions(+), 14 deletions(-)

diff --git a/include/net/addrconf.h b/include/net/addrconf.h
index f679877..9b1d42e 100644
--- a/include/net/addrconf.h
+++ b/include/net/addrconf.h
@@ -202,7 +202,7 @@ int ipv6_sock_ac_drop(struct sock *sk, int ifindex,
 		      const struct in6_addr *addr);
 void ipv6_sock_ac_close(struct sock *sk);
 
-int ipv6_dev_ac_inc(struct net_device *dev, const struct in6_addr *addr);
+int __ipv6_dev_ac_inc(struct inet6_dev *idev, const struct in6_addr *addr);
 int __ipv6_dev_ac_dec(struct inet6_dev *idev, const struct in6_addr *addr);
 bool ipv6_chk_acast_addr(struct net *net, struct net_device *dev,
 			 const struct in6_addr *addr);
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index ad4598f..6b6a373 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -1725,7 +1725,7 @@ static void addrconf_join_anycast(struct inet6_ifaddr *ifp)
 	ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len);
 	if (ipv6_addr_any(&addr))
 		return;
-	ipv6_dev_ac_inc(ifp->idev->dev, &addr);
+	__ipv6_dev_ac_inc(ifp->idev, &addr);
 }
 
 /* caller must hold RTNL */
diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c
index d10f2e2..bec8d14 100644
--- a/net/ipv6/anycast.c
+++ b/net/ipv6/anycast.c
@@ -122,7 +122,7 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, const struct in6_addr *addr)
 			goto error;
 	}
 
-	err = ipv6_dev_ac_inc(dev, addr);
+	err = __ipv6_dev_ac_inc(idev, addr);
 	if (!err) {
 		pac->acl_next = np->ipv6_ac_list;
 		np->ipv6_ac_list = pac;
@@ -215,20 +215,15 @@ static void aca_put(struct ifacaddr6 *ac)
 /*
  *	device anycast group inc (add if not found)
  */
-int ipv6_dev_ac_inc(struct net_device *dev, const struct in6_addr *addr)
+int __ipv6_dev_ac_inc(struct inet6_dev *idev, const struct in6_addr *addr)
 {
 	struct ifacaddr6 *aca;
-	struct inet6_dev *idev;
 	struct rt6_info *rt;
 	int err;
 
 	ASSERT_RTNL();
 
-	idev = in6_dev_get(dev);
-
-	if (idev == NULL)
-		return -EINVAL;
-
+	in6_dev_hold(idev);
 	write_lock_bh(&idev->lock);
 	if (idev->dead) {
 		err = -ENODEV;
@@ -267,7 +262,7 @@ int ipv6_dev_ac_inc(struct net_device *dev, const struct in6_addr *addr)
 	aca->aca_users = 1;
 	/* aca_tstamp should be updated upon changes */
 	aca->aca_cstamp = aca->aca_tstamp = jiffies;
-	atomic_set(&aca->aca_refcnt, 2);
+	atomic_set(&aca->aca_refcnt, 1);
 	spin_lock_init(&aca->aca_lock);
 
 	aca->aca_next = idev->ac_list;
@@ -276,9 +271,7 @@ int ipv6_dev_ac_inc(struct net_device *dev, const struct in6_addr *addr)
 
 	ip6_ins_rt(rt);
 
-	addrconf_join_solict(dev, &aca->aca_addr);
-
-	aca_put(aca);
+	addrconf_join_solict(idev->dev, &aca->aca_addr);
 	return 0;
 out:
 	write_unlock_bh(&idev->lock);
-- 
1.8.3.1

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

* [Patch net-next 4/5] ipv6: drop ipv6_sk_mc_lock in mcast
  2014-09-09 23:52 [Patch net-next 0/5] ipv6: clean up locking in anycast and mcast Cong Wang
                   ` (2 preceding siblings ...)
  2014-09-09 23:52 ` [Patch net-next 3/5] ipv6: clean up ipv6_dev_ac_inc() Cong Wang
@ 2014-09-09 23:52 ` Cong Wang
  2014-09-10 17:16   ` Sabrina Dubroca
  2014-09-09 23:52 ` [Patch net-next 5/5] ipv6: drop some rcu_read_lock " Cong Wang
  2014-09-10 20:01 ` [Patch net-next 0/5] ipv6: clean up locking in anycast and mcast David Miller
  5 siblings, 1 reply; 12+ messages in thread
From: Cong Wang @ 2014-09-09 23:52 UTC (permalink / raw)
  To: netdev; +Cc: Hannes Frederic Sowa, Hideaki YOSHIFUJI, David S. Miller,
	Cong Wang

Similarly the code is already protected by rtnl lock.

Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
---
 net/ipv6/mcast.c | 18 ++----------------
 1 file changed, 2 insertions(+), 16 deletions(-)

diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index 6833dd0..d2b7dd8 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -82,9 +82,6 @@ static void *__mld2_query_bugs[] __attribute__((__unused__)) = {
 
 static struct in6_addr mld2_all_mcr = MLD2_ALL_MCR_INIT;
 
-/* Big mc list lock for all the sockets */
-static DEFINE_SPINLOCK(ipv6_sk_mc_lock);
-
 static void igmp6_join_group(struct ifmcaddr6 *ma);
 static void igmp6_leave_group(struct ifmcaddr6 *ma);
 static void igmp6_timer_handler(unsigned long data);
@@ -210,10 +207,8 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr)
 		return err;
 	}
 
-	spin_lock(&ipv6_sk_mc_lock);
 	mc_lst->next = np->ipv6_mc_list;
 	rcu_assign_pointer(np->ipv6_mc_list, mc_lst);
-	spin_unlock(&ipv6_sk_mc_lock);
 
 	rcu_read_unlock();
 	rtnl_unlock();
@@ -235,17 +230,14 @@ int ipv6_sock_mc_drop(struct sock *sk, int ifindex, const struct in6_addr *addr)
 		return -EINVAL;
 
 	rtnl_lock();
-	spin_lock(&ipv6_sk_mc_lock);
 	for (lnk = &np->ipv6_mc_list;
-	     (mc_lst = rcu_dereference_protected(*lnk,
-			lockdep_is_held(&ipv6_sk_mc_lock))) != NULL;
+	     (mc_lst = rtnl_dereference(*lnk)) != NULL;
 	      lnk = &mc_lst->next) {
 		if ((ifindex == 0 || mc_lst->ifindex == ifindex) &&
 		    ipv6_addr_equal(&mc_lst->addr, addr)) {
 			struct net_device *dev;
 
 			*lnk = mc_lst->next;
-			spin_unlock(&ipv6_sk_mc_lock);
 
 			rcu_read_lock();
 			dev = dev_get_by_index_rcu(net, mc_lst->ifindex);
@@ -265,7 +257,6 @@ int ipv6_sock_mc_drop(struct sock *sk, int ifindex, const struct in6_addr *addr)
 			return 0;
 		}
 	}
-	spin_unlock(&ipv6_sk_mc_lock);
 	rtnl_unlock();
 
 	return -EADDRNOTAVAIL;
@@ -312,13 +303,10 @@ void ipv6_sock_mc_close(struct sock *sk)
 		return;
 
 	rtnl_lock();
-	spin_lock(&ipv6_sk_mc_lock);
-	while ((mc_lst = rcu_dereference_protected(np->ipv6_mc_list,
-				lockdep_is_held(&ipv6_sk_mc_lock))) != NULL) {
+	while ((mc_lst = rtnl_dereference(np->ipv6_mc_list)) != NULL) {
 		struct net_device *dev;
 
 		np->ipv6_mc_list = mc_lst->next;
-		spin_unlock(&ipv6_sk_mc_lock);
 
 		rcu_read_lock();
 		dev = dev_get_by_index_rcu(net, mc_lst->ifindex);
@@ -335,9 +323,7 @@ void ipv6_sock_mc_close(struct sock *sk)
 		atomic_sub(sizeof(*mc_lst), &sk->sk_omem_alloc);
 		kfree_rcu(mc_lst, rcu);
 
-		spin_lock(&ipv6_sk_mc_lock);
 	}
-	spin_unlock(&ipv6_sk_mc_lock);
 	rtnl_unlock();
 }
 
-- 
1.8.3.1

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

* [Patch net-next 5/5] ipv6: drop some rcu_read_lock in mcast
  2014-09-09 23:52 [Patch net-next 0/5] ipv6: clean up locking in anycast and mcast Cong Wang
                   ` (3 preceding siblings ...)
  2014-09-09 23:52 ` [Patch net-next 4/5] ipv6: drop ipv6_sk_mc_lock in mcast Cong Wang
@ 2014-09-09 23:52 ` Cong Wang
  2014-09-10 20:01 ` [Patch net-next 0/5] ipv6: clean up locking in anycast and mcast David Miller
  5 siblings, 0 replies; 12+ messages in thread
From: Cong Wang @ 2014-09-09 23:52 UTC (permalink / raw)
  To: netdev; +Cc: Hannes Frederic Sowa, Hideaki YOSHIFUJI, David S. Miller,
	Cong Wang

Similarly the code is already protected by rtnl lock.

Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
---
 net/ipv6/mcast.c | 17 ++++-------------
 1 file changed, 4 insertions(+), 13 deletions(-)

diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index d2b7dd8..255409c 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -171,7 +171,6 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr)
 	mc_lst->addr = *addr;
 
 	rtnl_lock();
-	rcu_read_lock();
 	if (ifindex == 0) {
 		struct rt6_info *rt;
 		rt = rt6_lookup(net, addr, NULL, 0, 0);
@@ -180,10 +179,9 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr)
 			ip6_rt_put(rt);
 		}
 	} else
-		dev = dev_get_by_index_rcu(net, ifindex);
+		dev = __dev_get_by_index(net, ifindex);
 
 	if (dev == NULL) {
-		rcu_read_unlock();
 		rtnl_unlock();
 		sock_kfree_s(sk, mc_lst, sizeof(*mc_lst));
 		return -ENODEV;
@@ -201,7 +199,6 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr)
 	err = ipv6_dev_mc_inc(dev, addr);
 
 	if (err) {
-		rcu_read_unlock();
 		rtnl_unlock();
 		sock_kfree_s(sk, mc_lst, sizeof(*mc_lst));
 		return err;
@@ -210,7 +207,6 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr)
 	mc_lst->next = np->ipv6_mc_list;
 	rcu_assign_pointer(np->ipv6_mc_list, mc_lst);
 
-	rcu_read_unlock();
 	rtnl_unlock();
 
 	return 0;
@@ -239,8 +235,7 @@ int ipv6_sock_mc_drop(struct sock *sk, int ifindex, const struct in6_addr *addr)
 
 			*lnk = mc_lst->next;
 
-			rcu_read_lock();
-			dev = dev_get_by_index_rcu(net, mc_lst->ifindex);
+			dev = __dev_get_by_index(net, mc_lst->ifindex);
 			if (dev != NULL) {
 				struct inet6_dev *idev = __in6_dev_get(dev);
 
@@ -249,7 +244,6 @@ int ipv6_sock_mc_drop(struct sock *sk, int ifindex, const struct in6_addr *addr)
 					__ipv6_dev_mc_dec(idev, &mc_lst->addr);
 			} else
 				(void) ip6_mc_leave_src(sk, mc_lst, NULL);
-			rcu_read_unlock();
 			rtnl_unlock();
 
 			atomic_sub(sizeof(*mc_lst), &sk->sk_omem_alloc);
@@ -308,8 +302,7 @@ void ipv6_sock_mc_close(struct sock *sk)
 
 		np->ipv6_mc_list = mc_lst->next;
 
-		rcu_read_lock();
-		dev = dev_get_by_index_rcu(net, mc_lst->ifindex);
+		dev = __dev_get_by_index(net, mc_lst->ifindex);
 		if (dev) {
 			struct inet6_dev *idev = __in6_dev_get(dev);
 
@@ -318,7 +311,6 @@ void ipv6_sock_mc_close(struct sock *sk)
 				__ipv6_dev_mc_dec(idev, &mc_lst->addr);
 		} else
 			(void) ip6_mc_leave_src(sk, mc_lst, NULL);
-		rcu_read_unlock();
 
 		atomic_sub(sizeof(*mc_lst), &sk->sk_omem_alloc);
 		kfree_rcu(mc_lst, rcu);
@@ -943,7 +935,7 @@ int ipv6_dev_mc_dec(struct net_device *dev, const struct in6_addr *addr)
 	struct inet6_dev *idev;
 	int err;
 
-	rcu_read_lock();
+	ASSERT_RTNL();
 
 	idev = __in6_dev_get(dev);
 	if (!idev)
@@ -951,7 +943,6 @@ int ipv6_dev_mc_dec(struct net_device *dev, const struct in6_addr *addr)
 	else
 		err = __ipv6_dev_mc_dec(idev, addr);
 
-	rcu_read_unlock();
 	return err;
 }
 
-- 
1.8.3.1

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

* Re: [Patch net-next 3/5] ipv6: clean up ipv6_dev_ac_inc()
  2014-09-09 23:52 ` [Patch net-next 3/5] ipv6: clean up ipv6_dev_ac_inc() Cong Wang
@ 2014-09-10 12:23   ` Hannes Frederic Sowa
  2014-09-10 21:32     ` Cong Wang
  0 siblings, 1 reply; 12+ messages in thread
From: Hannes Frederic Sowa @ 2014-09-10 12:23 UTC (permalink / raw)
  To: Cong Wang; +Cc: netdev, Hideaki YOSHIFUJI, David S. Miller

On Di, 2014-09-09 at 16:52 -0700, Cong Wang wrote:
> Make it accept inet6_dev, and rename it to __ipv6_dev_ac_inc()
> to reflect this change.
> 
> Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
> ---
>  include/net/addrconf.h |  2 +-
>  net/ipv6/addrconf.c    |  2 +-
>  net/ipv6/anycast.c     | 17 +++++------------
>  3 files changed, 7 insertions(+), 14 deletions(-)
> 
> diff --git a/include/net/addrconf.h b/include/net/addrconf.h
> index f679877..9b1d42e 100644
> --- a/include/net/addrconf.h
> +++ b/include/net/addrconf.h
> @@ -202,7 +202,7 @@ int ipv6_sock_ac_drop(struct sock *sk, int ifindex,
>  		      const struct in6_addr *addr);
>  void ipv6_sock_ac_close(struct sock *sk);
>  
> -int ipv6_dev_ac_inc(struct net_device *dev, const struct in6_addr *addr);
> +int __ipv6_dev_ac_inc(struct inet6_dev *idev, const struct in6_addr *addr);
>  int __ipv6_dev_ac_dec(struct inet6_dev *idev, const struct in6_addr *addr);
>  bool ipv6_chk_acast_addr(struct net *net, struct net_device *dev,
>  			 const struct in6_addr *addr);
> diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
> index ad4598f..6b6a373 100644
> --- a/net/ipv6/addrconf.c
> +++ b/net/ipv6/addrconf.c
> @@ -1725,7 +1725,7 @@ static void addrconf_join_anycast(struct inet6_ifaddr *ifp)
>  	ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len);
>  	if (ipv6_addr_any(&addr))
>  		return;
> -	ipv6_dev_ac_inc(ifp->idev->dev, &addr);
> +	__ipv6_dev_ac_inc(ifp->idev, &addr);
>  }
>  
>  /* caller must hold RTNL */
> diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c
> index d10f2e2..bec8d14 100644
> --- a/net/ipv6/anycast.c
> +++ b/net/ipv6/anycast.c
> @@ -122,7 +122,7 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, const struct in6_addr *addr)
>  			goto error;
>  	}
>  
> -	err = ipv6_dev_ac_inc(dev, addr);
> +	err = __ipv6_dev_ac_inc(idev, addr);
>  	if (!err) {
>  		pac->acl_next = np->ipv6_ac_list;
>  		np->ipv6_ac_list = pac;
> @@ -215,20 +215,15 @@ static void aca_put(struct ifacaddr6 *ac)
>  /*
>   *	device anycast group inc (add if not found)
>   */
> -int ipv6_dev_ac_inc(struct net_device *dev, const struct in6_addr *addr)
> +int __ipv6_dev_ac_inc(struct inet6_dev *idev, const struct in6_addr *addr)
>  {
>  	struct ifacaddr6 *aca;
> -	struct inet6_dev *idev;
>  	struct rt6_info *rt;
>  	int err;
>  
>  	ASSERT_RTNL();
>  
> -	idev = in6_dev_get(dev);
> -
> -	if (idev == NULL)
> -		return -EINVAL;
> -
> +	in6_dev_hold(idev);

Please move this in6_dev_hold down to where it gets attached to the
ifacaddr6 and remove the in6_dev_put from below the out: label.

>  	write_lock_bh(&idev->lock);
>  	if (idev->dead) {
>  		err = -ENODEV;
> @@ -267,7 +262,7 @@ int ipv6_dev_ac_inc(struct net_device *dev, const struct in6_addr *addr)
>  	aca->aca_users = 1;
>  	/* aca_tstamp should be updated upon changes */
>  	aca->aca_cstamp = aca->aca_tstamp = jiffies;
> -	atomic_set(&aca->aca_refcnt, 2);
> +	atomic_set(&aca->aca_refcnt, 1);
>  	spin_lock_init(&aca->aca_lock);
>  
>  	aca->aca_next = idev->ac_list;
> @@ -276,9 +271,7 @@ int ipv6_dev_ac_inc(struct net_device *dev, const struct in6_addr *addr)
>  
>  	ip6_ins_rt(rt);
>  
> -	addrconf_join_solict(dev, &aca->aca_addr);
> -
> -	aca_put(aca);

I am not sure why you changed the aca_refcnt code. idev->ac_list is only
protected by idev->lock and you publish one reference and unlock, thus
you need a second reference during addrconf_join_solict. All accesses
should also be protected by rtnl, so it shouldn't be a problem, but if
people review the code they might have problems to figure that out.
Maybe you can also remove the idev->lock?

> +	addrconf_join_solict(idev->dev, &aca->aca_addr);
>  	return 0;
>  out:
>  	write_unlock_bh(&idev->lock);

Thanks,
Hannes

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

* Re: [Patch net-next 4/5] ipv6: drop ipv6_sk_mc_lock in mcast
  2014-09-09 23:52 ` [Patch net-next 4/5] ipv6: drop ipv6_sk_mc_lock in mcast Cong Wang
@ 2014-09-10 17:16   ` Sabrina Dubroca
  2014-09-10 22:36     ` Cong Wang
  0 siblings, 1 reply; 12+ messages in thread
From: Sabrina Dubroca @ 2014-09-10 17:16 UTC (permalink / raw)
  To: Cong Wang
  Cc: netdev, Hannes Frederic Sowa, Hideaki YOSHIFUJI, David S. Miller

Hello,

2014-09-09, 16:52:17 -0700, Cong Wang wrote:
> Similarly the code is already protected by rtnl lock.
> 
> Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
> ---
>  net/ipv6/mcast.c | 18 ++----------------
>  1 file changed, 2 insertions(+), 16 deletions(-)
> 
> diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
> index 6833dd0..d2b7dd8 100644
> --- a/net/ipv6/mcast.c
> +++ b/net/ipv6/mcast.c
> @@ -82,9 +82,6 @@ static void *__mld2_query_bugs[] __attribute__((__unused__)) = {
>  
>  static struct in6_addr mld2_all_mcr = MLD2_ALL_MCR_INIT;
>  
> -/* Big mc list lock for all the sockets */
> -static DEFINE_SPINLOCK(ipv6_sk_mc_lock);
> -

Just a small thing: there are a few comments in the file that still
refer to this lock (as ipv6_sk_mc_lock or ip6_sk_mc_lock):

--
	/*
	 * changes to the ipv6_mc_list require the socket lock and
	 * a read lock on ip6_sk_mc_lock. We have the socket lock,
	 * so reading the list is safe.
	 */
--
	/* changes to psl require the socket lock, a read lock on
	 * on ipv6_sk_mc_lock and a write lock on pmc->sflock. We
	 * have the socket lock, so reading here is safe.
	 */
--
	/* callers have the socket lock and a write lock on ipv6_sk_mc_lock,
	 * so no other readers or writers of iml or its sflist
	 */
--

If you submit a v2 of this patchset, you could update them. Otherwise,
I'll do it later.


Thanks,

-- 
Sabrina

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

* Re: [Patch net-next 0/5] ipv6: clean up locking in anycast and mcast
  2014-09-09 23:52 [Patch net-next 0/5] ipv6: clean up locking in anycast and mcast Cong Wang
                   ` (4 preceding siblings ...)
  2014-09-09 23:52 ` [Patch net-next 5/5] ipv6: drop some rcu_read_lock " Cong Wang
@ 2014-09-10 20:01 ` David Miller
  2014-09-10 23:54   ` Cong Wang
  5 siblings, 1 reply; 12+ messages in thread
From: David Miller @ 2014-09-10 20:01 UTC (permalink / raw)
  To: xiyou.wangcong; +Cc: netdev, hannes, yoshfuji

From: Cong Wang <xiyou.wangcong@gmail.com>
Date: Tue,  9 Sep 2014 16:52:13 -0700

> This patchset cleans up the locking in anycast.c and mcast.c.
> 
> Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>

Please update this based upon the feedback you've received.

Thanks!

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

* Re: [Patch net-next 3/5] ipv6: clean up ipv6_dev_ac_inc()
  2014-09-10 12:23   ` Hannes Frederic Sowa
@ 2014-09-10 21:32     ` Cong Wang
  0 siblings, 0 replies; 12+ messages in thread
From: Cong Wang @ 2014-09-10 21:32 UTC (permalink / raw)
  To: Hannes Frederic Sowa
  Cc: Linux Kernel Network Developers, Hideaki YOSHIFUJI,
	David S. Miller

On Wed, Sep 10, 2014 at 5:23 AM, Hannes Frederic Sowa
<hannes@stressinduktion.org> wrote:
> On Di, 2014-09-09 at 16:52 -0700, Cong Wang wrote:
>> +     in6_dev_hold(idev);
>
> Please move this in6_dev_hold down to where it gets attached to the
> ifacaddr6 and remove the in6_dev_put from below the out: label.


I thought it is for idev->lock in case of idev becomes a wild pointer
as well, but it seems its callers or at least RTNL should guarantee
idev is still valid. So yeah, then we can probably move it down.

>
>>       write_lock_bh(&idev->lock);
>>       if (idev->dead) {
>>               err = -ENODEV;
>> @@ -267,7 +262,7 @@ int ipv6_dev_ac_inc(struct net_device *dev, const struct in6_addr *addr)
>>       aca->aca_users = 1;
>>       /* aca_tstamp should be updated upon changes */
>>       aca->aca_cstamp = aca->aca_tstamp = jiffies;
>> -     atomic_set(&aca->aca_refcnt, 2);
>> +     atomic_set(&aca->aca_refcnt, 1);
>>       spin_lock_init(&aca->aca_lock);
>>
>>       aca->aca_next = idev->ac_list;
>> @@ -276,9 +271,7 @@ int ipv6_dev_ac_inc(struct net_device *dev, const struct in6_addr *addr)
>>
>>       ip6_ins_rt(rt);
>>
>> -     addrconf_join_solict(dev, &aca->aca_addr);
>> -
>> -     aca_put(aca);
>
> I am not sure why you changed the aca_refcnt code. idev->ac_list is only
> protected by idev->lock and you publish one reference and unlock, thus
> you need a second reference during addrconf_join_solict. All accesses
> should also be protected by rtnl, so it shouldn't be a problem, but if
> people review the code they might have problems to figure that out.
> Maybe you can also remove the idev->lock?
>

I was misled by the code, it is not easy to understand this since there
is no comment. I will refactor the code to make it more readable and
of course in a separated patch.

Thanks.

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

* Re: [Patch net-next 4/5] ipv6: drop ipv6_sk_mc_lock in mcast
  2014-09-10 17:16   ` Sabrina Dubroca
@ 2014-09-10 22:36     ` Cong Wang
  0 siblings, 0 replies; 12+ messages in thread
From: Cong Wang @ 2014-09-10 22:36 UTC (permalink / raw)
  To: Sabrina Dubroca
  Cc: Linux Kernel Network Developers, Hannes Frederic Sowa,
	Hideaki YOSHIFUJI, David S. Miller

On Wed, Sep 10, 2014 at 10:16 AM, Sabrina Dubroca <sd@queasysnail.net> wrote:
>
> Just a small thing: there are a few comments in the file that still
> refer to this lock (as ipv6_sk_mc_lock or ip6_sk_mc_lock):
>

Yeah, I missed it. But it is already out of date since RCU conversion.
I will fix the comment in a separated patch in the next update.

Thanks.

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

* Re: [Patch net-next 0/5] ipv6: clean up locking in anycast and mcast
  2014-09-10 20:01 ` [Patch net-next 0/5] ipv6: clean up locking in anycast and mcast David Miller
@ 2014-09-10 23:54   ` Cong Wang
  0 siblings, 0 replies; 12+ messages in thread
From: Cong Wang @ 2014-09-10 23:54 UTC (permalink / raw)
  To: David Miller
  Cc: Linux Kernel Network Developers, Hannes Frederic Sowa,
	Hideaki YOSHIFUJI

On Wed, Sep 10, 2014 at 1:01 PM, David Miller <davem@davemloft.net> wrote:
> From: Cong Wang <xiyou.wangcong@gmail.com>
> Date: Tue,  9 Sep 2014 16:52:13 -0700
>
>> This patchset cleans up the locking in anycast.c and mcast.c.
>>
>> Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
>
> Please update this based upon the feedback you've received.
>

Sure thing, done.

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

end of thread, other threads:[~2014-09-10 23:54 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-09-09 23:52 [Patch net-next 0/5] ipv6: clean up locking in anycast and mcast Cong Wang
2014-09-09 23:52 ` [Patch net-next 1/5] ipv6: drop useless rcu_read_lock() in anycast Cong Wang
2014-09-09 23:52 ` [Patch net-next 2/5] ipv6: remove ipv6_sk_ac_lock Cong Wang
2014-09-09 23:52 ` [Patch net-next 3/5] ipv6: clean up ipv6_dev_ac_inc() Cong Wang
2014-09-10 12:23   ` Hannes Frederic Sowa
2014-09-10 21:32     ` Cong Wang
2014-09-09 23:52 ` [Patch net-next 4/5] ipv6: drop ipv6_sk_mc_lock in mcast Cong Wang
2014-09-10 17:16   ` Sabrina Dubroca
2014-09-10 22:36     ` Cong Wang
2014-09-09 23:52 ` [Patch net-next 5/5] ipv6: drop some rcu_read_lock " Cong Wang
2014-09-10 20:01 ` [Patch net-next 0/5] ipv6: clean up locking in anycast and mcast David Miller
2014-09-10 23:54   ` Cong Wang

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).