summaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorOlaf Kirch <olaf.kirch@oracle.com>2007-07-11 19:32:02 -0700
committerDavid S. Miller <davem@davemloft.net>2007-07-11 19:32:02 -0700
commit29578624e354f56143d92510fff33a8b2aaa2c03 (patch)
tree67d0f28264dbeacedde4882f1e76157894ba33ba /net
parent1fd05ba5a2f2aa8e7b9b52ef55df850e2e7d54c9 (diff)
[NET]: Fix races in net_rx_action vs netpoll.
Keep netpoll/poll_napi from messing with the poll_list. Only net_rx_action is allowed to manipulate the list. Signed-off-by: Olaf Kirch <olaf.kirch@oracle.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/core/netpoll.c8
1 files changed, 8 insertions, 0 deletions
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index de1b26aa5720..d1264e9a50a8 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -124,6 +124,13 @@ static void poll_napi(struct netpoll *np)
if (test_bit(__LINK_STATE_RX_SCHED, &np->dev->state) &&
npinfo->poll_owner != smp_processor_id() &&
spin_trylock(&npinfo->poll_lock)) {
+ /* When calling dev->poll from poll_napi, we may end up in
+ * netif_rx_complete. However, only the CPU to which the
+ * device was queued is allowed to remove it from poll_list.
+ * Setting POLL_LIST_FROZEN tells netif_rx_complete
+ * to leave the NAPI state alone.
+ */
+ set_bit(__LINK_STATE_POLL_LIST_FROZEN, &np->dev->state);
npinfo->rx_flags |= NETPOLL_RX_DROP;
atomic_inc(&trapped);
@@ -131,6 +138,7 @@ static void poll_napi(struct netpoll *np)
atomic_dec(&trapped);
npinfo->rx_flags &= ~NETPOLL_RX_DROP;
+ clear_bit(__LINK_STATE_POLL_LIST_FROZEN, &np->dev->state);
spin_unlock(&npinfo->poll_lock);
}
}