]> err.no Git - linux-2.6/commitdiff
pkt_sched: Use qdisc_lock() on already sampled root qdisc.
authorDavid S. Miller <davem@davemloft.net>
Sun, 3 Aug 2008 03:02:43 +0000 (20:02 -0700)
committerDavid S. Miller <davem@davemloft.net>
Sun, 3 Aug 2008 03:02:43 +0000 (20:02 -0700)
Based upon a bug report by Jeff Kirsher.

Don't use qdisc_root_lock() in these cases as the root
qdisc could have been changed, and we'd thus lock the
wrong object.

Tested by Emil S Tantilov who confirms that this seems
to fix the problem.

Signed-off-by: David S. Miller <davem@davemloft.net>
net/core/dev.c
net/sched/sch_generic.c

index 69320a56a084667d860ccbd4d4b5573e6977672d..da7acacf02b5d3e1b269355e13c03136f6c2c447 100644 (file)
@@ -1796,7 +1796,7 @@ gso:
        skb->tc_verd = SET_TC_AT(skb->tc_verd,AT_EGRESS);
 #endif
        if (q->enqueue) {
-               spinlock_t *root_lock = qdisc_root_lock(q);
+               spinlock_t *root_lock = qdisc_lock(q);
 
                spin_lock(root_lock);
 
@@ -1995,7 +1995,7 @@ static void net_tx_action(struct softirq_action *h)
                        smp_mb__before_clear_bit();
                        clear_bit(__QDISC_STATE_SCHED, &q->state);
 
-                       root_lock = qdisc_root_lock(q);
+                       root_lock = qdisc_lock(q);
                        if (spin_trylock(root_lock)) {
                                qdisc_run(q);
                                spin_unlock(root_lock);
index 9c9cd4d94890d1b1c5fb7d582af730f37248cfc0..7cf83b37459d0f08926baf49c07ce1ad9882b433 100644 (file)
@@ -29,7 +29,7 @@
 /* Main transmission queue. */
 
 /* Modifications to data participating in scheduling must be protected with
- * qdisc_root_lock(qdisc) spinlock.
+ * qdisc_lock(qdisc) spinlock.
  *
  * The idea is the following:
  * - enqueue, dequeue are serialized via qdisc root lock
@@ -126,7 +126,7 @@ static inline int qdisc_restart(struct Qdisc *q)
        if (unlikely((skb = dequeue_skb(q)) == NULL))
                return 0;
 
-       root_lock = qdisc_root_lock(q);
+       root_lock = qdisc_lock(q);
 
        /* And release qdisc */
        spin_unlock(root_lock);
@@ -507,7 +507,7 @@ errout:
 }
 EXPORT_SYMBOL(qdisc_create_dflt);
 
-/* Under qdisc_root_lock(qdisc) and BH! */
+/* Under qdisc_lock(qdisc) and BH! */
 
 void qdisc_reset(struct Qdisc *qdisc)
 {
@@ -543,7 +543,7 @@ static void __qdisc_destroy(struct rcu_head *head)
        kfree((char *) qdisc - qdisc->padded);
 }
 
-/* Under qdisc_root_lock(qdisc) and BH! */
+/* Under qdisc_lock(qdisc) and BH! */
 
 void qdisc_destroy(struct Qdisc *qdisc)
 {
@@ -659,7 +659,7 @@ static bool some_qdisc_is_running(struct net_device *dev, int lock)
 
                dev_queue = netdev_get_tx_queue(dev, i);
                q = dev_queue->qdisc;
-               root_lock = qdisc_root_lock(q);
+               root_lock = qdisc_lock(q);
 
                if (lock)
                        spin_lock_bh(root_lock);
@@ -735,7 +735,7 @@ static void shutdown_scheduler_queue(struct net_device *dev,
        struct Qdisc *qdisc_default = _qdisc_default;
 
        if (qdisc) {
-               spinlock_t *root_lock = qdisc_root_lock(qdisc);
+               spinlock_t *root_lock = qdisc_lock(qdisc);
 
                dev_queue->qdisc = qdisc_default;
                dev_queue->qdisc_sleeping = qdisc_default;