diff options
author | Akinobu Mita <akinobu.mita@gmail.com> | 2014-02-26 14:57:03 +0100 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2014-03-19 23:04:30 +0100 |
commit | 6c78cc06583344244628bf29aa5b5fe43ff5d04e (patch) | |
tree | 6ef80001e2fe6f27993cb708003092acf5ebd771 /drivers/scsi/scsi_debug.c | |
parent | [SCSI] scsi_debug: prepare to enable clustering (diff) | |
download | linux-6c78cc06583344244628bf29aa5b5fe43ff5d04e.tar.xz linux-6c78cc06583344244628bf29aa5b5fe43ff5d04e.zip |
[SCSI] scsi_debug: protect device access with atomic_rw lock
This change ensures that concurrent device access including ramdisk
storage, protection info, and provisioning map by read, write, and
unmap commands are protected with atomic_rw spinlock.
Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com>
Reviewed-by: Douglas Gilbert <dgilbert@interlog.com>
Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/scsi_debug.c')
-rw-r--r-- | drivers/scsi/scsi_debug.c | 12 |
1 files changed, 10 insertions, 2 deletions
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 004b98566c41..0bb1d49c3552 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -1888,17 +1888,19 @@ static int resp_read(struct scsi_cmnd *SCpnt, unsigned long long lba, return check_condition_result; } + read_lock_irqsave(&atomic_rw, iflags); + /* DIX + T10 DIF */ if (scsi_debug_dix && scsi_prot_sg_count(SCpnt)) { int prot_ret = prot_verify_read(SCpnt, lba, num, ei_lba); if (prot_ret) { + read_unlock_irqrestore(&atomic_rw, iflags); mk_sense_buffer(devip, ABORTED_COMMAND, 0x10, prot_ret); return illegal_condition_result; } } - read_lock_irqsave(&atomic_rw, iflags); ret = do_device_access(SCpnt, devip, lba, num, 0); read_unlock_irqrestore(&atomic_rw, iflags); if (ret == -1) @@ -2098,17 +2100,19 @@ static int resp_write(struct scsi_cmnd *SCpnt, unsigned long long lba, if (ret) return ret; + write_lock_irqsave(&atomic_rw, iflags); + /* DIX + T10 DIF */ if (scsi_debug_dix && scsi_prot_sg_count(SCpnt)) { int prot_ret = prot_verify_write(SCpnt, lba, num, ei_lba); if (prot_ret) { + write_unlock_irqrestore(&atomic_rw, iflags); mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x10, prot_ret); return illegal_condition_result; } } - write_lock_irqsave(&atomic_rw, iflags); ret = do_device_access(SCpnt, devip, lba, num, 1); if (scsi_debug_lbp()) map_region(lba, num); @@ -2187,6 +2191,7 @@ static int resp_unmap(struct scsi_cmnd * scmd, struct sdebug_dev_info * devip) struct unmap_block_desc *desc; unsigned int i, payload_len, descriptors; int ret; + unsigned long iflags; ret = check_readiness(scmd, 1, devip); if (ret) @@ -2208,6 +2213,8 @@ static int resp_unmap(struct scsi_cmnd * scmd, struct sdebug_dev_info * devip) desc = (void *)&buf[8]; + write_lock_irqsave(&atomic_rw, iflags); + for (i = 0 ; i < descriptors ; i++) { unsigned long long lba = get_unaligned_be64(&desc[i].lba); unsigned int num = get_unaligned_be32(&desc[i].blocks); @@ -2222,6 +2229,7 @@ static int resp_unmap(struct scsi_cmnd * scmd, struct sdebug_dev_info * devip) ret = 0; out: + write_unlock_irqrestore(&atomic_rw, iflags); kfree(buf); return ret; |