linux/net/sched
Herbert Xu d7811e623d [NET]: Drop tx lock in dev_watchdog_up
Fix lockdep warning with GRE, iptables and Speedtouch ADSL, PPP over ATM.

On Sat, Sep 02, 2006 at 08:39:28PM +0000, Krzysztof Halasa wrote:
> 
> =======================================================
> [ INFO: possible circular locking dependency detected ]
> -------------------------------------------------------
> swapper/0 is trying to acquire lock:
>  (&dev->queue_lock){-+..}, at: [<c02c8c46>] dev_queue_xmit+0x56/0x290
> 
> but task is already holding lock:
>  (&dev->_xmit_lock){-+..}, at: [<c02c8e14>] dev_queue_xmit+0x224/0x290
> 
> which lock already depends on the new lock.

This turns out to be a genuine bug.  The queue lock and xmit lock are
intentionally taken out of order.  Two things are supposed to prevent
dead-locks from occuring:

1) When we hold the queue_lock we're supposed to only do try_lock on the
tx_lock.

2) We always drop the queue_lock after taking the tx_lock and before doing
anything else.

> 
> the existing dependency chain (in reverse order) is:
> 
> -> #1 (&dev->_xmit_lock){-+..}:
>        [<c012e7b6>] lock_acquire+0x76/0xa0
>        [<c0336241>] _spin_lock_bh+0x31/0x40
>        [<c02d25a9>] dev_activate+0x69/0x120

This path obviously breaks assumption 1) and therefore can lead to ABBA
dead-locks.

I've looked at the history and there seems to be no reason for the lock
to be held at all in dev_watchdog_up.  The lock appeared in day one and
even there it was unnecessary.  In fact, people added __dev_watchdog_up
precisely in order to get around the tx lock there.

The function dev_watchdog_up is already serialised by rtnl_lock since
its only caller dev_activate is always called under it.

So here is a simple patch to remove the tx lock from dev_watchdog_up.
In 2.6.19 we can eliminate the unnecessary __dev_watchdog_up and
replace it with dev_watchdog_up.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
2006-09-18 00:22:30 -07:00
..
act_api.c [NET]: Conversions from kmalloc+memset to k(z|c)alloc. 2006-07-21 14:51:30 -07:00
act_gact.c Remove obsolete #include <linux/config.h> 2006-06-30 19:25:36 +02:00
act_ipt.c Remove obsolete #include <linux/config.h> 2006-06-30 19:25:36 +02:00
act_mirred.c Remove obsolete #include <linux/config.h> 2006-06-30 19:25:36 +02:00
act_pedit.c [NET]: Conversions from kmalloc+memset to k(z|c)alloc. 2006-07-21 14:51:30 -07:00
act_police.c [NET]: Conversions from kmalloc+memset to k(z|c)alloc. 2006-07-21 14:51:30 -07:00
act_simple.c Remove obsolete #include <linux/config.h> 2006-06-30 19:25:36 +02:00
cls_api.c Remove obsolete #include <linux/config.h> 2006-06-30 19:25:36 +02:00
cls_basic.c [NET]: Conversions from kmalloc+memset to k(z|c)alloc. 2006-07-21 14:51:30 -07:00
cls_fw.c [NET]: Conversions from kmalloc+memset to k(z|c)alloc. 2006-07-21 14:51:30 -07:00
cls_route.c [NET]: Conversions from kmalloc+memset to k(z|c)alloc. 2006-07-21 14:51:30 -07:00
cls_rsvp6.c
cls_rsvp.c
cls_rsvp.h [NET]: Conversions from kmalloc+memset to k(z|c)alloc. 2006-07-21 14:51:30 -07:00
cls_tcindex.c [NET]: Conversions from kmalloc+memset to k(z|c)alloc. 2006-07-21 14:51:30 -07:00
cls_u32.c [PKT_SCHED] cls_u32: Fix typo. 2006-08-17 16:29:54 -07:00
em_cmp.c Remove obsolete #include <linux/config.h> 2006-06-30 19:25:36 +02:00
em_meta.c [NET]: Conversions from kmalloc+memset to k(z|c)alloc. 2006-07-21 14:51:30 -07:00
em_nbyte.c Remove obsolete #include <linux/config.h> 2006-06-30 19:25:36 +02:00
em_text.c Remove obsolete #include <linux/config.h> 2006-06-30 19:25:36 +02:00
em_u32.c Remove obsolete #include <linux/config.h> 2006-06-30 19:25:36 +02:00
ematch.c [NET]: Conversions from kmalloc+memset to k(z|c)alloc. 2006-07-21 14:51:30 -07:00
estimator.c [NET]: Conversions from kmalloc+memset to k(z|c)alloc. 2006-07-21 14:51:30 -07:00
Kconfig
Makefile
sch_api.c [PKT_SCHED]: Return ENOENT if qdisc module is unavailable 2006-08-04 22:59:49 -07:00
sch_atm.c Remove obsolete #include <linux/config.h> 2006-06-30 19:25:36 +02:00
sch_blackhole.c Remove obsolete #include <linux/config.h> 2006-06-30 19:25:36 +02:00
sch_cbq.c [NET]: Conversions from kmalloc+memset to k(z|c)alloc. 2006-07-21 14:51:30 -07:00
sch_dsmark.c Remove obsolete #include <linux/config.h> 2006-06-30 19:25:36 +02:00
sch_fifo.c Remove obsolete #include <linux/config.h> 2006-06-30 19:25:36 +02:00
sch_generic.c [NET]: Drop tx lock in dev_watchdog_up 2006-09-18 00:22:30 -07:00
sch_gred.c [NET]: Conversions from kmalloc+memset to k(z|c)alloc. 2006-07-21 14:51:30 -07:00
sch_hfsc.c [NET]: Conversions from kmalloc+memset to k(z|c)alloc. 2006-07-21 14:51:30 -07:00
sch_htb.c [NET]: Conversions from kmalloc+memset to k(z|c)alloc. 2006-07-21 14:51:30 -07:00
sch_ingress.c Remove obsolete #include <linux/config.h> 2006-06-30 19:25:36 +02:00
sch_netem.c [PKT_SCHED] netem: Fix slab corruption with netem (2nd try) 2006-07-21 14:45:25 -07:00
sch_prio.c Remove obsolete #include <linux/config.h> 2006-06-30 19:25:36 +02:00
sch_red.c Remove obsolete #include <linux/config.h> 2006-06-30 19:25:36 +02:00
sch_sfq.c Remove obsolete #include <linux/config.h> 2006-06-30 19:25:36 +02:00
sch_tbf.c Remove obsolete #include <linux/config.h> 2006-06-30 19:25:36 +02:00
sch_teql.c