]> err.no Git - linux-2.6/commitdiff
[NET]: Fix dev->qdisc race for NETDEV_TX_LOCKED case
authorThomas Graf <tgraf@suug.ch>
Thu, 10 May 2007 11:02:41 +0000 (04:02 -0700)
committerDavid S. Miller <davem@sunset.davemloft.net>
Fri, 11 May 2007 06:47:39 +0000 (23:47 -0700)
When transmit fails with NETDEV_TX_LOCKED the skb is requeued
to dev->qdisc again. The dev->qdisc pointer is protected by
the queue lock which needs to be dropped when attempting to
transmit and acquired again before requeing. The problem is
that qdisc_restart() fetches the dev->qdisc pointer once and
stores it in the `q' variable which is invalidated when
dropping the queue_lock, therefore the variable needs to be
refreshed before requeueing.

Signed-off-by: Thomas Graf <tgraf@suug.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/sched/sch_generic.c

index 3385ee5925418d73da404e429c33b20f6db9f4a1..a8240c578772d402ea8bd510f901ff25154e4f66 100644 (file)
@@ -139,6 +139,7 @@ static inline int qdisc_restart(struct net_device *dev)
                                }
                                if (ret == NETDEV_TX_LOCKED && nolock) {
                                        spin_lock(&dev->queue_lock);
+                                       q = dev->qdisc;
                                        goto collision;
                                }
                        }