Patchwork [07/10] decnet: use RCU to find network devices

login
register
mail settings
Submitter stephen hemminger
Date Nov. 10, 2009, 5:54 p.m.
Message ID <20091110175647.615305929@vyatta.com>
Download mbox | patch
Permalink /patch/38081/
State Accepted
Delegated to: David Miller
Headers show

Comments

stephen hemminger - Nov. 10, 2009, 5:54 p.m.
When showing device statistics use RCU rather than read_lock(&dev_base_lock)
Compile tested only.

Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
steve@chygwyn.com - Nov. 10, 2009, 6:24 p.m.
Hi,

On Tue, Nov 10, 2009 at 10:50:53AM -0800, Stephen Hemminger wrote:
> On Tue, 10 Nov 2009 19:43:21 +0100
> Eric Dumazet <eric.dumazet@gmail.com> wrote:
> 
> > Stephen Hemminger a écrit :
> > > When showing device statistics use RCU rather than read_lock(&dev_base_lock)
> > > Compile tested only.
> > > 
> > > Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
> > > 
> > > --- a/net/decnet/dn_dev.c	2009-11-10 09:30:55.557376454 -0800
> > > +++ b/net/decnet/dn_dev.c	2009-11-10 09:40:03.847005394 -0800
> > > @@ -856,9 +856,7 @@ int dn_dev_bind_default(__le16 *addr)
> > >  	dev = dn_dev_get_default();
> > >  last_chance:
> > >  	if (dev) {
> > > -		read_lock(&dev_base_lock);
> > >  		rv = dn_dev_get_first(dev, addr);
> > > -		read_unlock(&dev_base_lock);
> > >  		dev_put(dev);
> > >  		if (rv == 0 || dev == init_net.loopback_dev)
> > >  			return rv;
> > > @@ -1323,18 +1321,18 @@ static inline int is_dn_dev(struct net_d
> > 
> > 
> > I dont understand this part. Why previous locking can be avoided ?
> 
> dn_dev_get_default acquires a reference on dev so the device can
> not go away.
> 
> It could be the original author meant to ensure the address list
> doesn't change. If so, then rtnl_lock() should have been used.

The original author has tried to remember what he was thinking when
he wrote this code :-)

I think you are right that it should be rtnl_lock() as we don't want
the address list changing at this point. On the other hand I notice
also that other bits of the code seem to be using dev_base_lock too.

Maybe this is a hang over from another era? I'll have to refresh
my memory some more before I can give a verdict on that I'm afraid,

Steve.

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Eric Dumazet - Nov. 10, 2009, 6:43 p.m.
Stephen Hemminger a écrit :
> When showing device statistics use RCU rather than read_lock(&dev_base_lock)
> Compile tested only.
> 
> Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
> 
> --- a/net/decnet/dn_dev.c	2009-11-10 09:30:55.557376454 -0800
> +++ b/net/decnet/dn_dev.c	2009-11-10 09:40:03.847005394 -0800
> @@ -856,9 +856,7 @@ int dn_dev_bind_default(__le16 *addr)
>  	dev = dn_dev_get_default();
>  last_chance:
>  	if (dev) {
> -		read_lock(&dev_base_lock);
>  		rv = dn_dev_get_first(dev, addr);
> -		read_unlock(&dev_base_lock);
>  		dev_put(dev);
>  		if (rv == 0 || dev == init_net.loopback_dev)
>  			return rv;
> @@ -1323,18 +1321,18 @@ static inline int is_dn_dev(struct net_d


I dont understand this part. Why previous locking can be avoided ?
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
stephen hemminger - Nov. 10, 2009, 6:50 p.m.
On Tue, 10 Nov 2009 19:43:21 +0100
Eric Dumazet <eric.dumazet@gmail.com> wrote:

> Stephen Hemminger a écrit :
> > When showing device statistics use RCU rather than read_lock(&dev_base_lock)
> > Compile tested only.
> > 
> > Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
> > 
> > --- a/net/decnet/dn_dev.c	2009-11-10 09:30:55.557376454 -0800
> > +++ b/net/decnet/dn_dev.c	2009-11-10 09:40:03.847005394 -0800
> > @@ -856,9 +856,7 @@ int dn_dev_bind_default(__le16 *addr)
> >  	dev = dn_dev_get_default();
> >  last_chance:
> >  	if (dev) {
> > -		read_lock(&dev_base_lock);
> >  		rv = dn_dev_get_first(dev, addr);
> > -		read_unlock(&dev_base_lock);
> >  		dev_put(dev);
> >  		if (rv == 0 || dev == init_net.loopback_dev)
> >  			return rv;
> > @@ -1323,18 +1321,18 @@ static inline int is_dn_dev(struct net_d
> 
> 
> I dont understand this part. Why previous locking can be avoided ?

dn_dev_get_default acquires a reference on dev so the device can
not go away.

It could be the original author meant to ensure the address list
doesn't change. If so, then rtnl_lock() should have been used.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Eric Dumazet - Nov. 10, 2009, 7:25 p.m.
Stephen Hemminger a écrit :
> On Tue, 10 Nov 2009 19:43:21 +0100
> Eric Dumazet <eric.dumazet@gmail.com> wrote:
> 
>> Stephen Hemminger a écrit :
>>> When showing device statistics use RCU rather than read_lock(&dev_base_lock)
>>> Compile tested only.
>>>
>>> Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
>>>
>>> --- a/net/decnet/dn_dev.c	2009-11-10 09:30:55.557376454 -0800
>>> +++ b/net/decnet/dn_dev.c	2009-11-10 09:40:03.847005394 -0800
>>> @@ -856,9 +856,7 @@ int dn_dev_bind_default(__le16 *addr)
>>>  	dev = dn_dev_get_default();
>>>  last_chance:
>>>  	if (dev) {
>>> -		read_lock(&dev_base_lock);
>>>  		rv = dn_dev_get_first(dev, addr);
>>> -		read_unlock(&dev_base_lock);
>>>  		dev_put(dev);
>>>  		if (rv == 0 || dev == init_net.loopback_dev)
>>>  			return rv;
>>> @@ -1323,18 +1321,18 @@ static inline int is_dn_dev(struct net_d
>>
>> I dont understand this part. Why previous locking can be avoided ?
> 
> dn_dev_get_default acquires a reference on dev so the device can
> not go away.
> 
> It could be the original author meant to ensure the address list
> doesn't change. If so, then rtnl_lock() should have been used.

Hmm... I spot some bugs during my previous round of patches, so maybe
this is a real bug... We should double check.


--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
David Miller - Nov. 11, 2009, 6:49 a.m.
From: Stephen Hemminger <shemminger@vyatta.com>
Date: Tue, 10 Nov 2009 09:54:53 -0800

> When showing device statistics use RCU rather than read_lock(&dev_base_lock)
> Compile tested only.
> 
> Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>

Applied.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Patch

--- a/net/decnet/dn_dev.c	2009-11-10 09:30:55.557376454 -0800
+++ b/net/decnet/dn_dev.c	2009-11-10 09:40:03.847005394 -0800
@@ -856,9 +856,7 @@  int dn_dev_bind_default(__le16 *addr)
 	dev = dn_dev_get_default();
 last_chance:
 	if (dev) {
-		read_lock(&dev_base_lock);
 		rv = dn_dev_get_first(dev, addr);
-		read_unlock(&dev_base_lock);
 		dev_put(dev);
 		if (rv == 0 || dev == init_net.loopback_dev)
 			return rv;
@@ -1323,18 +1321,18 @@  static inline int is_dn_dev(struct net_d
 }
 
 static void *dn_dev_seq_start(struct seq_file *seq, loff_t *pos)
-	__acquires(&dev_base_lock)
+	__acquires(rcu)
 {
 	int i;
 	struct net_device *dev;
 
-	read_lock(&dev_base_lock);
+	rcu_read_lock();
 
 	if (*pos == 0)
 		return SEQ_START_TOKEN;
 
 	i = 1;
-	for_each_netdev(&init_net, dev) {
+	for_each_netdev_rcu(&init_net, dev) {
 		if (!is_dn_dev(dev))
 			continue;
 
@@ -1355,7 +1353,7 @@  static void *dn_dev_seq_next(struct seq_
 	if (v == SEQ_START_TOKEN)
 		dev = net_device_entry(&init_net.dev_base_head);
 
-	for_each_netdev_continue(&init_net, dev) {
+	for_each_netdev_continue_rcu(&init_net, dev) {
 		if (!is_dn_dev(dev))
 			continue;
 
@@ -1366,9 +1364,9 @@  static void *dn_dev_seq_next(struct seq_
 }
 
 static void dn_dev_seq_stop(struct seq_file *seq, void *v)
-	__releases(&dev_base_lock)
+	__releases(rcu)
 {
-	read_unlock(&dev_base_lock);
+	rcu_read_unlock();
 }
 
 static char *dn_type2asc(char type)