netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Possible race with br_del_if()
@ 2005-08-18 21:40 Ryan Harper
  2005-08-18 22:12 ` Stephen Hemminger
  2005-10-11 20:33 ` [PATCH] br: fix race on bridge del if Stephen Hemminger
  0 siblings, 2 replies; 9+ messages in thread
From: Ryan Harper @ 2005-08-18 21:40 UTC (permalink / raw)
  To: shemminger; +Cc: netdev

Hello,

I've encountered several oops when adding and removing interfaces from
bridges while using Xen.  Most of the details are available [1]here.
The short of it is the following sequence:

CPU0                    CPU1
add_del_if()            unregister_netdevice()  
br_del_if()             notifier_call_chain(NETDEV_UNREGISTER) 
del_nbp()               
br_stp_disable_port()   // port->state == BR_STATE_DISABLED
                        br_device_event() // dev->br_port != NULL yet
                                          // event is NETDEV_UNREGISTER
                        br_del_if()
                        sysfs_remove_dir(p)
                        kobject_del()
                        dget(dentry)
                        BUG_ON(!atomic_read(&dentry->d_count)

This sequence doesn't happen all of the time.  In many cases, CPU0 moves
along right into destroy_nbp() which sets dev->br_port = NULL, and
be_device_event check (p == NULL) hits and a second br_del_if() isn't
called.

The attached patch is a workaround for the double case, but I'm not sure
if is the right way to deal with this issue, or if it any issue at all.

1. http://bugzilla.xensource.com/bugzilla/show_bug.cgi?id=90

-- 
Ryan Harper
Software Engineer; Linux Technology Center
IBM Corp., Austin, Tx
(512) 838-9253   T/L: 678-9253
ryanh@us.ibm.com


diffstat output:
 br_if.c |    2 +-
 1 files changed, 1 insertion(+), 1 deletion(-)

Signed-off-by: Ryan Harper <ryanh@us.ibm.com>
---
Simple workaround for double call to br_del_if().

Signed-off-by: Ryan Harper <ryanh@us.ibm.com>

--- linux-2.6.12/net/bridge/br_if.c	2005-06-17 14:48:29.000000000 -0500
+++ linux-2.6.12-xen0-smp/net/bridge/br_if.c	2005-08-18 15:17:27.302615846 -0500
@@ -382,7 +382,7 @@
 {
 	struct net_bridge_port *p = dev->br_port;
 	
-	if (!p || p->br != br) 
+	if (!p || p->br != br || p->state == BR_STATE_DISABLED)
 		return -EINVAL;
 
 	br_sysfs_removeif(p);

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

* Re: Possible race with br_del_if()
  2005-08-18 21:40 Possible race with br_del_if() Ryan Harper
@ 2005-08-18 22:12 ` Stephen Hemminger
  2005-08-18 22:23   ` Ryan Harper
  2005-10-11 20:33 ` [PATCH] br: fix race on bridge del if Stephen Hemminger
  1 sibling, 1 reply; 9+ messages in thread
From: Stephen Hemminger @ 2005-08-18 22:12 UTC (permalink / raw)
  To: Ryan Harper; +Cc: netdev

On Thu, 18 Aug 2005 16:40:36 -0500
Ryan Harper <ryanh@us.ibm.com> wrote:

> Hello,
> 
> I've encountered several oops when adding and removing interfaces from
> bridges while using Xen.  Most of the details are available [1]here.
> The short of it is the following sequence:

Doesn't the mutex in RTNL work right?  or are you calling
routines with out asserting it?

> CPU0                    CPU1
> add_del_if()            unregister_netdevice()  
> br_del_if()             notifier_call_chain(NETDEV_UNREGISTER) 
> del_nbp()               
> br_stp_disable_port()   // port->state == BR_STATE_DISABLED
>                         br_device_event() // dev->br_port != NULL yet
>                                           // event is NETDEV_UNREGISTER
>                         br_del_if()
>                         sysfs_remove_dir(p)
>                         kobject_del()
>                         dget(dentry)
>                         BUG_ON(!atomic_read(&dentry->d_count)
> 
> This sequence doesn't happen all of the time.  In many cases, CPU0 moves
> along right into destroy_nbp() which sets dev->br_port = NULL, and
> be_device_event check (p == NULL) hits and a second br_del_if() isn't
> called.
> 
> The attached patch is a workaround for the double case, but I'm not sure
> if is the right way to deal with this issue, or if it any issue at all.
> 
> 1. http://bugzilla.xensource.com/bugzilla/show_bug.cgi?id=90
> 

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

* Re: Possible race with br_del_if()
  2005-08-18 22:12 ` Stephen Hemminger
@ 2005-08-18 22:23   ` Ryan Harper
  2005-08-18 22:35     ` Stephen Hemminger
  0 siblings, 1 reply; 9+ messages in thread
From: Ryan Harper @ 2005-08-18 22:23 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: netdev

* Stephen Hemminger <shemminger@osdl.org> [2005-08-18 17:11]:
> On Thu, 18 Aug 2005 16:40:36 -0500
> Ryan Harper <ryanh@us.ibm.com> wrote:
> 
> > Hello,
> > 
> > I've encountered several oops when adding and removing interfaces from
> > bridges while using Xen.  Most of the details are available [1]here.
> > The short of it is the following sequence:
> 
> Doesn't the mutex in RTNL work right?  or are you calling
> routines with out asserting it?

unregister_netdevice asserts RTNL, add_del_if() in br_ioctl.c doesn't
seem to do so.  I don't see it down dev_get_by_index() path either.  It
looks like any caller of add_del_if() isn't asserting RTNL.  The two
callers I see are:

br_dev_ioctl() in br_ioctl.c
old_dev_ioctl() in br_ioctl.c


-- 
Ryan Harper
Software Engineer; Linux Technology Center
IBM Corp., Austin, Tx
(512) 838-9253   T/L: 678-9253
ryanh@us.ibm.com

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

* Re: Possible race with br_del_if()
  2005-08-18 22:23   ` Ryan Harper
@ 2005-08-18 22:35     ` Stephen Hemminger
  2005-08-18 22:56       ` Ryan Harper
  2005-08-19 19:10       ` Ryan Harper
  0 siblings, 2 replies; 9+ messages in thread
From: Stephen Hemminger @ 2005-08-18 22:35 UTC (permalink / raw)
  To: Ryan Harper; +Cc: netdev

On Thu, 18 Aug 2005 17:23:23 -0500
Ryan Harper <ryanh@us.ibm.com> wrote:

> * Stephen Hemminger <shemminger@osdl.org> [2005-08-18 17:11]:
> > On Thu, 18 Aug 2005 16:40:36 -0500
> > Ryan Harper <ryanh@us.ibm.com> wrote:
> > 
> > > Hello,
> > > 
> > > I've encountered several oops when adding and removing interfaces from
> > > bridges while using Xen.  Most of the details are available [1]here.
> > > The short of it is the following sequence:
> > 
> > Doesn't the mutex in RTNL work right?  or are you calling
> > routines with out asserting it?
> 
> unregister_netdevice asserts RTNL, add_del_if() in br_ioctl.c doesn't
> seem to do so.  I don't see it down dev_get_by_index() path either.  It
> looks like any caller of add_del_if() isn't asserting RTNL.  The two
> callers I see are:
> 
> br_dev_ioctl() in br_ioctl.c
> old_dev_ioctl() in br_ioctl.c

But the pat to br_dev_ioctl() is via the socket ioctl and that
should already have gotten RTNL.


dev_ioctl
	rtnl_lock()
	dev_ifsioc()
		dev->do_ioctl --> br_dev_ioctl

			

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

* Re: Possible race with br_del_if()
  2005-08-18 22:35     ` Stephen Hemminger
@ 2005-08-18 22:56       ` Ryan Harper
  2005-08-19 19:10       ` Ryan Harper
  1 sibling, 0 replies; 9+ messages in thread
From: Ryan Harper @ 2005-08-18 22:56 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: netdev

* Stephen Hemminger <shemminger@osdl.org> [2005-08-18 17:36]:
> On Thu, 18 Aug 2005 17:23:23 -0500
> Ryan Harper <ryanh@us.ibm.com> wrote:
> 
> > * Stephen Hemminger <shemminger@osdl.org> [2005-08-18 17:11]:
> > > On Thu, 18 Aug 2005 16:40:36 -0500
> > > Ryan Harper <ryanh@us.ibm.com> wrote:
> > > 
> > > > Hello,
> > > > 
> > > > I've encountered several oops when adding and removing interfaces from
> > > > bridges while using Xen.  Most of the details are available [1]here.
> > > > The short of it is the following sequence:
> > > 
> > > Doesn't the mutex in RTNL work right?  or are you calling
> > > routines with out asserting it?
> > 
> > unregister_netdevice asserts RTNL, add_del_if() in br_ioctl.c doesn't
> > seem to do so.  I don't see it down dev_get_by_index() path either.  It
> > looks like any caller of add_del_if() isn't asserting RTNL.  The two
> > callers I see are:
> > 
> > br_dev_ioctl() in br_ioctl.c
> > old_dev_ioctl() in br_ioctl.c
> 
> But the pat to br_dev_ioctl() is via the socket ioctl and that
> should already have gotten RTNL.
> 
> 
> dev_ioctl
> 	rtnl_lock()
> 	dev_ifsioc()
> 		dev->do_ioctl --> br_dev_ioctl

Hrm. OK.  It sounds like both paths are doing the right thing w.r.t
asserting RTNL, but br_device_event() still gets called with:

1) dev->br_port != NULL 
2) dev->br_port->state = BR_STATE_DISABLED
3) event = NETDEV_UNREGISTER

which results in br_del_if() being called a second time on the same
port.  

Some of the other cases  (NETDEV_FEAT_CHANGE, NETDEV_CHANGE) do a state
check before calling a subsequent function.  Does it make sense for
br_del_if() to be called on a port whose state is BR_STATE_DISABLED?

-- 
Ryan Harper
Software Engineer; Linux Technology Center
IBM Corp., Austin, Tx
(512) 838-9253   T/L: 678-9253
ryanh@us.ibm.com

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

* Re: Possible race with br_del_if()
  2005-08-18 22:35     ` Stephen Hemminger
  2005-08-18 22:56       ` Ryan Harper
@ 2005-08-19 19:10       ` Ryan Harper
  2005-08-19 19:40         ` Stephen Hemminger
  1 sibling, 1 reply; 9+ messages in thread
From: Ryan Harper @ 2005-08-19 19:10 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: netdev

* Stephen Hemminger <shemminger@osdl.org> [2005-08-18 17:36]:
> On Thu, 18 Aug 2005 17:23:23 -0500
> Ryan Harper <ryanh@us.ibm.com> wrote:
> 
> > * Stephen Hemminger <shemminger@osdl.org> [2005-08-18 17:11]:
> > > On Thu, 18 Aug 2005 16:40:36 -0500
> > > Ryan Harper <ryanh@us.ibm.com> wrote:
> > > 
> > > > Hello,
> > > > 
> > > > I've encountered several oops when adding and removing interfaces from
> > > > bridges while using Xen.  Most of the details are available [1]here.
> > > > The short of it is the following sequence:
> > > 
> > > Doesn't the mutex in RTNL work right?  or are you calling
> > > routines with out asserting it?
> > 
> > unregister_netdevice asserts RTNL, add_del_if() in br_ioctl.c doesn't
> > seem to do so.  I don't see it down dev_get_by_index() path either.  It
> > looks like any caller of add_del_if() isn't asserting RTNL.  The two
> > callers I see are:
> > 
> > br_dev_ioctl() in br_ioctl.c
> > old_dev_ioctl() in br_ioctl.c
> 
> But the pat to br_dev_ioctl() is via the socket ioctl and that
> should already have gotten RTNL.
> 
> 
> dev_ioctl
> 	rtnl_lock()
> 	dev_ifsioc()
> 		dev->do_ioctl --> br_dev_ioctl


Just to follow-up, the issue was a race between the call_rcu() callback
for destroy_nbp() and an unregister_netdev() call.  Sometimes the
br_device_event() routine was triggered and destroy_nbp() had not been
run yet leaving dev->br_port non-NULL to which br_device_event then
correctly calls br_del_if().

We caused this by issuing a brctl delif from userspace scripts and
having a in kernel handler invoke unregister_netdev() call.  

Our fix is to not bother calling brctl delif because the
unregister_netdev() call will automatically remove the device from the
bridge when the notify_call_chain() kicks in from
unregister_netdevice().  

-- 
Ryan Harper
Software Engineer; Linux Technology Center
IBM Corp., Austin, Tx
(512) 838-9253   T/L: 678-9253
ryanh@us.ibm.com

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

* Re: Possible race with br_del_if()
  2005-08-19 19:10       ` Ryan Harper
@ 2005-08-19 19:40         ` Stephen Hemminger
  0 siblings, 0 replies; 9+ messages in thread
From: Stephen Hemminger @ 2005-08-19 19:40 UTC (permalink / raw)
  To: Ryan Harper; +Cc: netdev

On Fri, 19 Aug 2005 14:10:52 -0500
Ryan Harper <ryanh@us.ibm.com> wrote:

> * Stephen Hemminger <shemminger@osdl.org> [2005-08-18 17:36]:
> > On Thu, 18 Aug 2005 17:23:23 -0500
> > Ryan Harper <ryanh@us.ibm.com> wrote:
> > 
> > > * Stephen Hemminger <shemminger@osdl.org> [2005-08-18 17:11]:
> > > > On Thu, 18 Aug 2005 16:40:36 -0500
> > > > Ryan Harper <ryanh@us.ibm.com> wrote:
> > > > 
> > > > > Hello,
> > > > > 
> > > > > I've encountered several oops when adding and removing interfaces from
> > > > > bridges while using Xen.  Most of the details are available [1]here.
> > > > > The short of it is the following sequence:
> > > > 
> > > > Doesn't the mutex in RTNL work right?  or are you calling
> > > > routines with out asserting it?
> > > 
> > > unregister_netdevice asserts RTNL, add_del_if() in br_ioctl.c doesn't
> > > seem to do so.  I don't see it down dev_get_by_index() path either.  It
> > > looks like any caller of add_del_if() isn't asserting RTNL.  The two
> > > callers I see are:
> > > 
> > > br_dev_ioctl() in br_ioctl.c
> > > old_dev_ioctl() in br_ioctl.c
> > 
> > But the pat to br_dev_ioctl() is via the socket ioctl and that
> > should already have gotten RTNL.
> > 
> > 
> > dev_ioctl
> > 	rtnl_lock()
> > 	dev_ifsioc()
> > 		dev->do_ioctl --> br_dev_ioctl
> 
> 
> Just to follow-up, the issue was a race between the call_rcu() callback
> for destroy_nbp() and an unregister_netdev() call.  Sometimes the
> br_device_event() routine was triggered and destroy_nbp() had not been
> run yet leaving dev->br_port non-NULL to which br_device_event then
> correctly calls br_del_if().
> 
> We caused this by issuing a brctl delif from userspace scripts and
> having a in kernel handler invoke unregister_netdev() call.  
> 
> Our fix is to not bother calling brctl delif because the
> unregister_netdev() call will automatically remove the device from the
> bridge when the notify_call_chain() kicks in from
> unregister_netdevice().  

I'll get back to you, this needs some review, I have a bunch of old
test suites to dig up for it.

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

* [PATCH] br: fix race on bridge del if
  2005-08-18 21:40 Possible race with br_del_if() Ryan Harper
  2005-08-18 22:12 ` Stephen Hemminger
@ 2005-10-11 20:33 ` Stephen Hemminger
  2005-10-12 22:10   ` David S. Miller
  1 sibling, 1 reply; 9+ messages in thread
From: Stephen Hemminger @ 2005-10-11 20:33 UTC (permalink / raw)
  To: Ryan Harper, David S. Miller; +Cc: netdev, Chris Wright, Greg KH

This fixes the RCU race on bridge delete interface.  Basically,
the network device has to be detached from the bridge in the first
step (pre-RCU), rather than later. At that point, no more bridge traffic
will come in, and the other code will not think that network device
is part of a bridge.

This should also fix the XEN test problems. If there is another
2.6.13-stable, add it as well.

Signed-off-by: Stephen Hemminger <shemminger@osdl.org>

Index: nexgate-test/net/bridge/br_if.c
===================================================================
--- nexgate-test.orig/net/bridge/br_if.c
+++ nexgate-test/net/bridge/br_if.c
@@ -79,7 +79,6 @@ static void destroy_nbp(struct net_bridg
 {
 	struct net_device *dev = p->dev;
 
-	dev->br_port = NULL;
 	p->br = NULL;
 	p->dev = NULL;
 	dev_put(dev);
@@ -100,6 +99,7 @@ static void del_nbp(struct net_bridge_po
 	struct net_bridge *br = p->br;
 	struct net_device *dev = p->dev;
 
+	dev->br_port = NULL;
 	dev_set_promiscuity(dev, -1);
 
 	spin_lock_bh(&br->lock);

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

* Re: [PATCH] br: fix race on bridge del if
  2005-10-11 20:33 ` [PATCH] br: fix race on bridge del if Stephen Hemminger
@ 2005-10-12 22:10   ` David S. Miller
  0 siblings, 0 replies; 9+ messages in thread
From: David S. Miller @ 2005-10-12 22:10 UTC (permalink / raw)
  To: shemminger; +Cc: ryanh, netdev, chrisw, greg

From: Stephen Hemminger <shemminger@osdl.org>
Date: Tue, 11 Oct 2005 13:33:28 -0700

> This fixes the RCU race on bridge delete interface.  Basically,
> the network device has to be detached from the bridge in the first
> step (pre-RCU), rather than later. At that point, no more bridge traffic
> will come in, and the other code will not think that network device
> is part of a bridge.
> 
> This should also fix the XEN test problems. If there is another
> 2.6.13-stable, add it as well.
> 
> Signed-off-by: Stephen Hemminger <shemminger@osdl.org>

Applied, thanks Stephen.

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

end of thread, other threads:[~2005-10-12 22:10 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-08-18 21:40 Possible race with br_del_if() Ryan Harper
2005-08-18 22:12 ` Stephen Hemminger
2005-08-18 22:23   ` Ryan Harper
2005-08-18 22:35     ` Stephen Hemminger
2005-08-18 22:56       ` Ryan Harper
2005-08-19 19:10       ` Ryan Harper
2005-08-19 19:40         ` Stephen Hemminger
2005-10-11 20:33 ` [PATCH] br: fix race on bridge del if Stephen Hemminger
2005-10-12 22:10   ` David S. Miller

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).