From e6fb3b2a1da675a89838b8d5002512ab61342dd6 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Fri, 3 Dec 2010 11:44:38 +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. (Merged r2913 from the trunk.) git-svn-id: http://svn.code.sf.net/p/scst/svn/branches/2.0.0.x@2915 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 e12c21232..c87860d48 100644 --- a/scst/src/dev_handlers/scst_vdisk.c +++ b/scst/src/dev_handlers/scst_vdisk.c @@ -2607,12 +2607,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)) @@ -2625,7 +2626,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);