diff options
author | David S. Miller <davem@davemloft.net> | 2008-08-19 07:00:36 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-08-19 07:00:36 -0400 |
commit | 195648bbc5ae0848e82f771ecf4cd7497054c212 (patch) | |
tree | 644bc8685cab5f83225558888a4398cd0c93c919 /net/core | |
parent | d2805395aadc105d7228511eb0f42d9eea912003 (diff) |
pkt_sched: Prevent livelock in TX queue running.
If dev_deactivate() is trying to quiesce the queue, it
is theoretically possible for another cpu to livelock
trying to process that queue. This happens because
dev_deactivate() grabs the queue spinlock as it checks
the queue state, whereas net_tx_action() does a trylock
and reschedules the qdisc if it hits the lock.
This breaks the livelock by adding a check on
__QDISC_STATE_DEACTIVATED to net_tx_action() when
the trylock fails.
Based upon feedback from Herbert Xu and Jarek Poplawski.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core')
-rw-r--r-- | net/core/dev.c | 4 |
1 files changed, 3 insertions, 1 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index 8d133802372b..60c51f765887 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -1990,7 +1990,9 @@ static void net_tx_action(struct softirq_action *h) | |||
1990 | qdisc_run(q); | 1990 | qdisc_run(q); |
1991 | spin_unlock(root_lock); | 1991 | spin_unlock(root_lock); |
1992 | } else { | 1992 | } else { |
1993 | __netif_reschedule(q); | 1993 | if (!test_bit(__QDISC_STATE_DEACTIVATED, |
1994 | &q->state)) | ||
1995 | __netif_reschedule(q); | ||
1994 | } | 1996 | } |
1995 | } | 1997 | } |
1996 | } | 1998 | } |