diff options
author | David S. Miller <davem@davemloft.net> | 2008-08-02 23:02:43 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-08-02 23:02:43 -0400 |
commit | 5fb662297b8a4bdadd60371c34b760efca948ebc (patch) | |
tree | ef1def70cfa440ab3d367f6f67d466227ffdf0ef /net/sched/sch_generic.c | |
parent | 82f97b8d3cb3982ec97e081598c671fab2c321b0 (diff) |
pkt_sched: Use qdisc_lock() on already sampled root qdisc.
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>
Diffstat (limited to 'net/sched/sch_generic.c')
-rw-r--r-- | net/sched/sch_generic.c | 12 |
1 files changed, 6 insertions, 6 deletions
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index 9c9cd4d94890..7cf83b37459d 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c | |||
@@ -29,7 +29,7 @@ | |||
29 | /* Main transmission queue. */ | 29 | /* Main transmission queue. */ |
30 | 30 | ||
31 | /* Modifications to data participating in scheduling must be protected with | 31 | /* Modifications to data participating in scheduling must be protected with |
32 | * qdisc_root_lock(qdisc) spinlock. | 32 | * qdisc_lock(qdisc) spinlock. |
33 | * | 33 | * |
34 | * The idea is the following: | 34 | * The idea is the following: |
35 | * - enqueue, dequeue are serialized via qdisc root lock | 35 | * - enqueue, dequeue are serialized via qdisc root lock |
@@ -126,7 +126,7 @@ static inline int qdisc_restart(struct Qdisc *q) | |||
126 | if (unlikely((skb = dequeue_skb(q)) == NULL)) | 126 | if (unlikely((skb = dequeue_skb(q)) == NULL)) |
127 | return 0; | 127 | return 0; |
128 | 128 | ||
129 | root_lock = qdisc_root_lock(q); | 129 | root_lock = qdisc_lock(q); |
130 | 130 | ||
131 | /* And release qdisc */ | 131 | /* And release qdisc */ |
132 | spin_unlock(root_lock); | 132 | spin_unlock(root_lock); |
@@ -507,7 +507,7 @@ errout: | |||
507 | } | 507 | } |
508 | EXPORT_SYMBOL(qdisc_create_dflt); | 508 | EXPORT_SYMBOL(qdisc_create_dflt); |
509 | 509 | ||
510 | /* Under qdisc_root_lock(qdisc) and BH! */ | 510 | /* Under qdisc_lock(qdisc) and BH! */ |
511 | 511 | ||
512 | void qdisc_reset(struct Qdisc *qdisc) | 512 | void qdisc_reset(struct Qdisc *qdisc) |
513 | { | 513 | { |
@@ -543,7 +543,7 @@ static void __qdisc_destroy(struct rcu_head *head) | |||
543 | kfree((char *) qdisc - qdisc->padded); | 543 | kfree((char *) qdisc - qdisc->padded); |
544 | } | 544 | } |
545 | 545 | ||
546 | /* Under qdisc_root_lock(qdisc) and BH! */ | 546 | /* Under qdisc_lock(qdisc) and BH! */ |
547 | 547 | ||
548 | void qdisc_destroy(struct Qdisc *qdisc) | 548 | void qdisc_destroy(struct Qdisc *qdisc) |
549 | { | 549 | { |
@@ -659,7 +659,7 @@ static bool some_qdisc_is_running(struct net_device *dev, int lock) | |||
659 | 659 | ||
660 | dev_queue = netdev_get_tx_queue(dev, i); | 660 | dev_queue = netdev_get_tx_queue(dev, i); |
661 | q = dev_queue->qdisc; | 661 | q = dev_queue->qdisc; |
662 | root_lock = qdisc_root_lock(q); | 662 | root_lock = qdisc_lock(q); |
663 | 663 | ||
664 | if (lock) | 664 | if (lock) |
665 | spin_lock_bh(root_lock); | 665 | spin_lock_bh(root_lock); |
@@ -735,7 +735,7 @@ static void shutdown_scheduler_queue(struct net_device *dev, | |||
735 | struct Qdisc *qdisc_default = _qdisc_default; | 735 | struct Qdisc *qdisc_default = _qdisc_default; |
736 | 736 | ||
737 | if (qdisc) { | 737 | if (qdisc) { |
738 | spinlock_t *root_lock = qdisc_root_lock(qdisc); | 738 | spinlock_t *root_lock = qdisc_lock(qdisc); |
739 | 739 | ||
740 | dev_queue->qdisc = qdisc_default; | 740 | dev_queue->qdisc = qdisc_default; |
741 | dev_queue->qdisc_sleeping = qdisc_default; | 741 | dev_queue->qdisc_sleeping = qdisc_default; |