Subject: Re: netif_tx_disable vs netif_stop_queue (possible races?)

From: Evgeniy Polyakov <[email-masked]>
Date: Sat, 10 Jun 2006 21:15:40 +0400

On Sat, Jun 10, 2006 at 05:40:39PM +0100, Daniel Drake ([email-masked]) wrote:
> Evgeniy Polyakov wrote:
> >On Sat, Jun 10, 2006 at 01:42:21PM +0100, Daniel Drake ([email-masked]) 
> >wrote:
> >>Herbert Xu wrote:
> >>>Correct.  All callers of hard_start_xmit do so under RCU or equivalent
> >>>locks so they must be complete by the time synchronize_net() returns.
> >>Does this hold for other operations? Such as:
> >>
> >>- The netdev->set_mac_address function
> >>- The wireless ioctl's (SIOCSIWESSID, etc)
> >>
> >>Are these also guaranteed to have returned after synchronize_net()?
> >
> >None of above calls is protected with RCU (except set_mac_address()
> >called through ioctl, which is performed under read_lock which disables
> >preemtption), so they still can run after synchronize_net().
> >
> >But if you are talking about synchronize_net() inside
> >unregister_netdevice(), which is called from 
> >usbnet_disconnect()->unregister_netdev(), than it is safe.
> 
> Are you referring to set_mac_address in the above statement, or both 
> set_mac_address *and* the wireless ioctls?

oth calls have the same nature actually, and both calls are not
protected by RCU.

> I'm basically just looking to clarify that after unregister_netdev has 
> completed, none of the following can be still in progress on any CPU, 
> and none of the following can be triggered again:
> 
> 1. hard_start_xmit handler
> 2. set_mac_address handler
> 3. WX ioctls
> 
> It's logical that this is the case, but the code doesn't make that very 
> clear (and would certainly result in many potential ZD1211 races if this 
> was not the case).

set_mac_address() and wireless ioctls are protected by rtnl.
unregister_netdevice()  is called under rtnl protection too.
But hard_start_xmit() is not protected (and can not be protected in all
situations) by sleeping semaphore (like rtnl), 
so instead it runs under RCU, which is synchronized in synchronize_net()
inside unregister_netdevice().

> Daniel

-- 
	Evgeniy Polyakov