block/IDE/interrupt lockup
PATCH 1/1 block/IDE/interrupt lockup
Marcelo,
my blk_grow_request_list() patch in -pre5 is buggy. It can cause boot-time lockups. The window is fairly small, but I just hit it.
drivers/ide/ide-probe.c:init_irq() does cli().
It calls down to blk_init_free_list() andblk_grow_request_list().
blk_grow_request_list() does spin_unlock_irq(). Which is illegal inside cli(). An interrupt comes in and the CPU locks up in irq_enter(), spinning on global_irq_lock, which this CPU already holds.
Below is the patch. (That's the last spin_lock_irq() anyone will be seeing from me :))
Andre, init_irq() is somewhat broken - it appears to be assuming that cli() will disable interrupts, but it's
calling functions which can sleep. If these functions
_do_ sleep, interrupts will be enabled, which is presumably not what IDE wants to happen.
drivers/block/ll_rw_blk.c renamed from drivers/block/ll_rw_blk.c~ide-lockup +6 -4
@@ -336,14 +336,16 @@ void generic_unplug_device(void *data)*/ int blk_grow_request_list (request_queue_t *q,int nr_requests) { -spin_lock_irq (&io_request_lock); +unsigned long flags; + +spin_lock_irqsave (&io_request_lock, flags);while (q->nr_requests < nr_requests) {struct request *rq;int rw; -spin_unlock_irq (&io_request_lock); +spin_unlock_irqrestore (&io_request_lock, flags); rq =kmem_cache_alloc (request_cachep,SLAB_KERNEL ); -spin_lock_irq (&io_request_lock); +spin_lock_irqsave (&io_request_lock, flags);if (rq ==NULL )break ;memset (rq,0 ,sizeof (*rq));
@@ -356,7 +358,7 @@ int blk_grow_request_list(request_queue_ q->batch_requests = q->nr_requests /4 ;if (q->batch_requests >32 ) q->batch_requests =32 ; -spin_unlock_irq (&io_request_lock); +spin_unlock_irqrestore (&io_request_lock, flags);return q->nr_requests; }
-