pkt_sched: Prevent livelock in TX queue running.
David S. Miller [Tue, 19 Aug 2008 11:00:36 +0000 (04:00 -0700)]
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>

net/core/dev.c

index 8d13380..60c51f7 100644 (file)
@@ -1990,7 +1990,9 @@ static void net_tx_action(struct softirq_action *h)
                                qdisc_run(q);
                                spin_unlock(root_lock);
                        } else {
-                               __netif_reschedule(q);
+                               if (!test_bit(__QDISC_STATE_DEACTIVATED,
+                                             &q->state))
+                                       __netif_reschedule(q);
                        }
                }
        }