Message ID | 1360248961-30721-1-git-send-email-nhorman@tuxdriver.com |
---|---|
State | Changes Requested, archived |
Delegated to: | David Miller |
Headers | show |
On Thu, 2013-02-07 at 09:56 -0500, Neil Horman wrote: > With my recent commit I introduced two sparse warnings. Looking closer there > were a few more in the same file, so I fixed them all up. Basic rcu pointer > dereferencing suff > - npinfo = np->dev->npinfo; > + /* rtnl_dereference would be preferable here but > + * rcu_cleanup_netpoll path can put us in here safely without > + * holding the rtnl, so plain rcu_dereference it is > + */ > + npinfo = rcu_dereference(np->dev->npinfo); > if (!npinfo) > return; > Are you sure it wont trigger a LOCKDEP complain (CONFIG_PROVE_RCU=y) ? -- 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
On Thu, Feb 07, 2013 at 07:52:56AM -0800, Eric Dumazet wrote: > On Thu, 2013-02-07 at 09:56 -0500, Neil Horman wrote: > > With my recent commit I introduced two sparse warnings. Looking closer there > > were a few more in the same file, so I fixed them all up. Basic rcu pointer > > dereferencing suff > > > - npinfo = np->dev->npinfo; > > + /* rtnl_dereference would be preferable here but > > + * rcu_cleanup_netpoll path can put us in here safely without > > + * holding the rtnl, so plain rcu_dereference it is > > + */ > > + npinfo = rcu_dereference(np->dev->npinfo); > > if (!npinfo) > > return; > > > > Are you sure it wont trigger a LOCKDEP complain (CONFIG_PROVE_RCU=y) ? > Hm, looking at it, you're probably right. We're not holding the rcu_read_lock, and I'd forgotten that rcu_dereference implicitly checks that rcu_read_lock is held. I guess, since the only paths that we get here on are in a bh rcu quiescence point or with the rtnl held we should probably make this: rcu_dereference_protected(np->dev->npinfo, rtnl_locked() || in_interrupt()); Although, thinking about this further somewhat begs the question as to how we prevent one context from calling __netpoll_cleanup in a path holding rtnl, while in parallel calling __netpoll_cleanup from the rcu callback. That might not be a huge deal as __netpoll_cleanup uses spinlocks to do list modification, and an atomic_dec_and_test to gate the free, but it still seems ugly. What do you think? > > -- 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
On Thu, 2013-02-07 at 13:37 -0500, Neil Horman wrote: > On Thu, Feb 07, 2013 at 07:52:56AM -0800, Eric Dumazet wrote: > > On Thu, 2013-02-07 at 09:56 -0500, Neil Horman wrote: > > > With my recent commit I introduced two sparse warnings. Looking closer there > > > were a few more in the same file, so I fixed them all up. Basic rcu pointer > > > dereferencing suff > > > > > - npinfo = np->dev->npinfo; > > > + /* rtnl_dereference would be preferable here but > > > + * rcu_cleanup_netpoll path can put us in here safely without > > > + * holding the rtnl, so plain rcu_dereference it is > > > + */ > > > + npinfo = rcu_dereference(np->dev->npinfo); > > > if (!npinfo) > > > return; > > > > > > > Are you sure it wont trigger a LOCKDEP complain (CONFIG_PROVE_RCU=y) ? > > > Hm, looking at it, you're probably right. We're not holding the rcu_read_lock, > and I'd forgotten that rcu_dereference implicitly checks that rcu_read_lock is > held. I guess, since the only paths that we get here on are in a bh rcu > quiescence point or with the rtnl held we should probably make this: > > rcu_dereference_protected(np->dev->npinfo, rtnl_locked() || in_interrupt()); > > Although, thinking about this further somewhat begs the question as to how we > prevent one context from calling __netpoll_cleanup in a path holding rtnl, while > in parallel calling __netpoll_cleanup from the rcu callback. That might not be > a huge deal as __netpoll_cleanup uses spinlocks to do list modification, and an > atomic_dec_and_test to gate the free, but it still seems ugly. > > What do you think? I think you could use rcu_dereference_check(p, lockdep_rtnl_is_held() || something) -- 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
On Thu, Feb 07, 2013 at 07:25:33PM -0800, Eric Dumazet wrote: > On Thu, 2013-02-07 at 13:37 -0500, Neil Horman wrote: > > On Thu, Feb 07, 2013 at 07:52:56AM -0800, Eric Dumazet wrote: > > > On Thu, 2013-02-07 at 09:56 -0500, Neil Horman wrote: > > > > With my recent commit I introduced two sparse warnings. Looking closer there > > > > were a few more in the same file, so I fixed them all up. Basic rcu pointer > > > > dereferencing suff > > > > > > > - npinfo = np->dev->npinfo; > > > > + /* rtnl_dereference would be preferable here but > > > > + * rcu_cleanup_netpoll path can put us in here safely without > > > > + * holding the rtnl, so plain rcu_dereference it is > > > > + */ > > > > + npinfo = rcu_dereference(np->dev->npinfo); > > > > if (!npinfo) > > > > return; > > > > > > > > > > Are you sure it wont trigger a LOCKDEP complain (CONFIG_PROVE_RCU=y) ? > > > > > Hm, looking at it, you're probably right. We're not holding the rcu_read_lock, > > and I'd forgotten that rcu_dereference implicitly checks that rcu_read_lock is > > held. I guess, since the only paths that we get here on are in a bh rcu > > quiescence point or with the rtnl held we should probably make this: > > > > rcu_dereference_protected(np->dev->npinfo, rtnl_locked() || in_interrupt()); > > > > Although, thinking about this further somewhat begs the question as to how we > > prevent one context from calling __netpoll_cleanup in a path holding rtnl, while > > in parallel calling __netpoll_cleanup from the rcu callback. That might not be > > a huge deal as __netpoll_cleanup uses spinlocks to do list modification, and an > > atomic_dec_and_test to gate the free, but it still seems ugly. > > > > What do you think? > > I think you could use > > rcu_dereference_check(p, lockdep_rtnl_is_held() || something) > Actually, I think all we need to do is take the rcu_read_lock and use rcu_dereference directly. __netpoll_cleanup doesn't actually change the dev->npinfo pointer itself, thats handled by the caller, always under protection of the rtnl, so here we just need to ensure that no one changes npifo while we're using it Neil > > -- 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
On Fri, 2013-02-08 at 10:47 -0500, Neil Horman wrote: > Actually, I think all we need to do is take the rcu_read_lock and use > rcu_dereference directly. __netpoll_cleanup doesn't actually change the > dev->npinfo pointer itself, thats handled by the caller, always under protection > of the rtnl, so here we just need to ensure that no one changes npifo while > we're using it SGTM ;) -- 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
On Fri, Feb 08, 2013 at 08:44:43AM -0800, Eric Dumazet wrote: > On Fri, 2013-02-08 at 10:47 -0500, Neil Horman wrote: > > > Actually, I think all we need to do is take the rcu_read_lock and use > > rcu_dereference directly. __netpoll_cleanup doesn't actually change the > > dev->npinfo pointer itself, thats handled by the caller, always under protection > > of the rtnl, so here we just need to ensure that no one changes npifo while > > we're using it > > SGTM ;) > Testing it out now. The more I look at this the more I'm concerned that there are other problems with netpoll in the release path. Shocking...I know :) Neil > > -- 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
I was fixing some sparse warnings in netpoll from a previous commit, and it was
pointed out to me that one of the rcu_dereferences that I fixed up in
__netpoll_cleanup might not have been correct. On investigation I found that
rtnl_dereference should have been the correct macro to use, but we had a path in
which we weren't properly holding the rtnl lock. This patch series fixes up the
locking in the __netpoll_free_rcu path, and then properly corrects the sparse
warnings in the netpoll.c file that I previously introduced.
Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
CC: David Miller <davem@davemloft.net>
CC: fengguang.wu@intel.com
CC: eric.dumazet@gmail.com
CC: Cong Wang <amwang@redhat.com>
--
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
From: Neil Horman <nhorman@tuxdriver.com> Date: Mon, 11 Feb 2013 15:25:29 -0500 > I was fixing some sparse warnings in netpoll from a previous commit, and it was > pointed out to me that one of the rcu_dereferences that I fixed up in > __netpoll_cleanup might not have been correct. On investigation I found that > rtnl_dereference should have been the correct macro to use, but we had a path in > which we weren't properly holding the rtnl lock. This patch series fixes up the > locking in the __netpoll_free_rcu path, and then properly corrects the sparse > warnings in the netpoll.c file that I previously introduced. > > Signed-off-by: Neil Horman <nhorman@tuxdriver.com> I happen to know that this is meant for net-next, but you really need to state that clearly in your patch submissions. -- 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
On Mon, Feb 11, 2013 at 04:11:35PM -0500, David Miller wrote: > From: Neil Horman <nhorman@tuxdriver.com> > Date: Mon, 11 Feb 2013 15:25:29 -0500 > > > I was fixing some sparse warnings in netpoll from a previous commit, and it was > > pointed out to me that one of the rcu_dereferences that I fixed up in > > __netpoll_cleanup might not have been correct. On investigation I found that > > rtnl_dereference should have been the correct macro to use, but we had a path in > > which we weren't properly holding the rtnl lock. This patch series fixes up the > > locking in the __netpoll_free_rcu path, and then properly corrects the sparse > > warnings in the netpoll.c file that I previously introduced. > > > > Signed-off-by: Neil Horman <nhorman@tuxdriver.com> > > I happen to know that this is meant for net-next, but you really need > to state that clearly in your patch submissions. > Understood, sorry Dave. Neil -- 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
diff --git a/net/core/netpoll.c b/net/core/netpoll.c index edcd9ad..1c829c0 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -205,7 +205,7 @@ static void netpoll_poll_dev(struct net_device *dev) * the dev_open/close paths use this to block netpoll activity * while changing device state */ - if (!mutex_trylock(&dev->npinfo->dev_lock)) + if (!mutex_trylock(&ni->dev_lock)) return; if (!dev || !netif_running(dev)) @@ -220,7 +220,7 @@ static void netpoll_poll_dev(struct net_device *dev) poll_napi(dev); - mutex_unlock(&dev->npinfo->dev_lock); + mutex_unlock(&ni->dev_lock); if (dev->flags & IFF_SLAVE) { if (ni) { @@ -1054,7 +1054,7 @@ int __netpoll_setup(struct netpoll *np, struct net_device *ndev, gfp_t gfp) goto free_npinfo; } } else { - npinfo = ndev->npinfo; + npinfo = rtnl_dereference(ndev->npinfo); atomic_inc(&npinfo->refcnt); } @@ -1234,7 +1234,11 @@ void __netpoll_cleanup(struct netpoll *np) struct netpoll_info *npinfo; unsigned long flags; - npinfo = np->dev->npinfo; + /* rtnl_dereference would be preferable here but + * rcu_cleanup_netpoll path can put us in here safely without + * holding the rtnl, so plain rcu_dereference it is + */ + npinfo = rcu_dereference(np->dev->npinfo); if (!npinfo) return;