From d0547fe613eaf14d9d968e32117f508646d08039 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Fri, 3 Dec 2010 11:35:31 +0000 Subject: [PATCH] scst/scst_vdisk: Made error handling in bi_end_io function IRQ-safe since bi_end_io functions must be IRQ-safe. A quote from a discussion between Alan Cox, Mikulas Patocka and Jens Axboe (http://lkml.org/lkml/2008/7/2/69): > >Right, that wont work of course. Completions are typically done through > >a softirq, so it is not currently done with hard interrupts disabled. > > I thought, from hardirq - that's what IDE is doing. And they are called > with interrupts disabled (maybe unless you specify unmaskirq, which is not > default). What block driver does completions with softirq? ... and why? The key word is 'typically', the old IDE driver really isn't used very much. The SCSI layer and eg cciss uses the block layer softirq completions, so that is what 99% of the uses will be. The patch itself was provided by Arne Redlich. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@2913 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- scst/src/dev_handlers/scst_vdisk.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scst/src/dev_handlers/scst_vdisk.c b/scst/src/dev_handlers/scst_vdisk.c index 059bb8bdf..8f336264e 100644 --- a/scst/src/dev_handlers/scst_vdisk.c +++ b/scst/src/dev_handlers/scst_vdisk.c @@ -2866,12 +2866,13 @@ static void blockio_endio(struct bio *bio, int error) if (unlikely(error != 0)) { static DEFINE_SPINLOCK(blockio_endio_lock); + unsigned long flags; PRINT_ERROR("cmd %p returned error %d", blockio_work->cmd, error); /* To protect from several bios finishing simultaneously */ - spin_lock_bh(&blockio_endio_lock); + spin_lock_irqsave(&blockio_endio_lock, flags); #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) if (bio->bi_rw & (1 << BIO_RW)) @@ -2884,7 +2885,7 @@ static void blockio_endio(struct bio *bio, int error) scst_set_cmd_error(blockio_work->cmd, SCST_LOAD_SENSE(scst_sense_read_error)); - spin_unlock_bh(&blockio_endio_lock); + spin_unlock_irqrestore(&blockio_endio_lock, flags); } blockio_check_finish(blockio_work);