Re: [PATCH 2/7] netpoll: make __netpoll_cleanup non-block
From: Neil Horman <nhorman@tuxdriver.com>
Date: 2012-07-27 18:40:46
Also in:
bridge, lkml
On Fri, Jul 27, 2012 at 11:37:59PM +0800, Cong Wang wrote:
Like the previous patch, slave_disable_netpoll() and __netpoll_cleanup() may be called with read_lock() held too, so we should make them non-block, by moving the cleanup and kfree() to call_rcu_bh() callbacks. Cc: "David S. Miller" <davem@davemloft.net> Signed-off-by: Cong Wang <redacted> --- drivers/net/bonding/bond_main.c | 4 +-- include/linux/netpoll.h | 3 ++ net/8021q/vlan_dev.c | 6 +---- net/bridge/br_device.c | 6 +---- net/core/netpoll.c | 42 +++++++++++++++++++++++++++++--------- 5 files changed, 38 insertions(+), 23 deletions(-) <snip>
quoted hunk ↗ jump to hunk
struct netpoll_info *npinfo;@@ -903,20 +921,24 @@ void __netpoll_cleanup(struct netpoll *np) ops->ndo_netpoll_cleanup(np->dev); RCU_INIT_POINTER(np->dev->npinfo, NULL); + call_rcu_bh(&npinfo->rcu, rcu_cleanup_netpoll_info); + } +} +EXPORT_SYMBOL_GPL(__netpoll_cleanup); - /* avoid racing with NAPI reading npinfo */ - synchronize_rcu_bh(); +static void rcu_cleanup_netpoll(struct rcu_head *rcu_head) +{ + struct netpoll *np = container_of(rcu_head, struct netpoll, rcu); - skb_queue_purge(&npinfo->arp_tx); - skb_queue_purge(&npinfo->txq); - cancel_delayed_work_sync(&npinfo->tx_work); + __netpoll_cleanup(np); + kfree(np); +} - /* clean after last, unfinished work */ - __skb_queue_purge(&npinfo->txq); - kfree(npinfo); - } +void __netpoll_free_rcu(struct netpoll *np) +{ + call_rcu_bh(&np->rcu, rcu_cleanup_netpoll);
Here, and above I see you using an rcu_head to defer cleanup, until after all pointer uses are dropped, but I don't see any modification of code points that dereference any struct netpoll pointers to include rcu_read_lock()/rcu_read_unlock(). Without those using rcu to defer cleanup is pointless, as the rcu code won't know when its safe to run. You're no better off that you would be just calling __netpoll_cleanup directly. Neil
}
-EXPORT_SYMBOL_GPL(__netpoll_cleanup);
+EXPORT_SYMBOL_GPL(__netpoll_free_rcu);
void netpoll_cleanup(struct netpoll *np)
{
--
1.7.7.6