From: Thomas Graf Date: Thu, 10 May 2007 11:02:41 +0000 (-0700) Subject: [NET]: Fix dev->qdisc race for NETDEV_TX_LOCKED case X-Git-Tag: v2.6.22-rc1~34^2~12 X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5830725f8a36908111ecccf2899d06d6dcf54d45;p=linux-2.6 [NET]: Fix dev->qdisc race for NETDEV_TX_LOCKED case 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 Signed-off-by: David S. Miller --- diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index 3385ee5925..a8240c5787 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c @@ -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; } }