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/core/dev.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/core/dev.c')
-rw-r--r-- | net/core/dev.c | 4 |
1 files changed, 2 insertions, 2 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index 69320a56a084..da7acacf02b5 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -1796,7 +1796,7 @@ gso: | |||
1796 | skb->tc_verd = SET_TC_AT(skb->tc_verd,AT_EGRESS); | 1796 | skb->tc_verd = SET_TC_AT(skb->tc_verd,AT_EGRESS); |
1797 | #endif | 1797 | #endif |
1798 | if (q->enqueue) { | 1798 | if (q->enqueue) { |
1799 | spinlock_t *root_lock = qdisc_root_lock(q); | 1799 | spinlock_t *root_lock = qdisc_lock(q); |
1800 | 1800 | ||
1801 | spin_lock(root_lock); | 1801 | spin_lock(root_lock); |
1802 | 1802 | ||
@@ -1995,7 +1995,7 @@ static void net_tx_action(struct softirq_action *h) | |||
1995 | smp_mb__before_clear_bit(); | 1995 | smp_mb__before_clear_bit(); |
1996 | clear_bit(__QDISC_STATE_SCHED, &q->state); | 1996 | clear_bit(__QDISC_STATE_SCHED, &q->state); |
1997 | 1997 | ||
1998 | root_lock = qdisc_root_lock(q); | 1998 | root_lock = qdisc_lock(q); |
1999 | if (spin_trylock(root_lock)) { | 1999 | if (spin_trylock(root_lock)) { |
2000 | qdisc_run(q); | 2000 | qdisc_run(q); |
2001 | spin_unlock(root_lock); | 2001 | spin_unlock(root_lock); |