diff options
author | Akinobu Mita <akinobu.mita@gmail.com> | 2014-02-26 08:57:03 -0500 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2014-03-19 18:04:30 -0400 |
commit | 6c78cc06583344244628bf29aa5b5fe43ff5d04e (patch) | |
tree | 6ef80001e2fe6f27993cb708003092acf5ebd771 /drivers/scsi | |
parent | be4e11be99dbb36308760595ee848ef51713b4b0 (diff) |
[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')
-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, | |||
1888 | return check_condition_result; | 1888 | return check_condition_result; |
1889 | } | 1889 | } |
1890 | 1890 | ||
1891 | read_lock_irqsave(&atomic_rw, iflags); | ||
1892 | |||
1891 | /* DIX + T10 DIF */ | 1893 | /* DIX + T10 DIF */ |
1892 | if (scsi_debug_dix && scsi_prot_sg_count(SCpnt)) { | 1894 | if (scsi_debug_dix && scsi_prot_sg_count(SCpnt)) { |
1893 | int prot_ret = prot_verify_read(SCpnt, lba, num, ei_lba); | 1895 | int prot_ret = prot_verify_read(SCpnt, lba, num, ei_lba); |
1894 | 1896 | ||
1895 | if (prot_ret) { | 1897 | if (prot_ret) { |
1898 | read_unlock_irqrestore(&atomic_rw, iflags); | ||
1896 | mk_sense_buffer(devip, ABORTED_COMMAND, 0x10, prot_ret); | 1899 | mk_sense_buffer(devip, ABORTED_COMMAND, 0x10, prot_ret); |
1897 | return illegal_condition_result; | 1900 | return illegal_condition_result; |
1898 | } | 1901 | } |
1899 | } | 1902 | } |
1900 | 1903 | ||
1901 | read_lock_irqsave(&atomic_rw, iflags); | ||
1902 | ret = do_device_access(SCpnt, devip, lba, num, 0); | 1904 | ret = do_device_access(SCpnt, devip, lba, num, 0); |
1903 | read_unlock_irqrestore(&atomic_rw, iflags); | 1905 | read_unlock_irqrestore(&atomic_rw, iflags); |
1904 | if (ret == -1) | 1906 | if (ret == -1) |
@@ -2098,17 +2100,19 @@ static int resp_write(struct scsi_cmnd *SCpnt, unsigned long long lba, | |||
2098 | if (ret) | 2100 | if (ret) |
2099 | return ret; | 2101 | return ret; |
2100 | 2102 | ||
2103 | write_lock_irqsave(&atomic_rw, iflags); | ||
2104 | |||
2101 | /* DIX + T10 DIF */ | 2105 | /* DIX + T10 DIF */ |
2102 | if (scsi_debug_dix && scsi_prot_sg_count(SCpnt)) { | 2106 | if (scsi_debug_dix && scsi_prot_sg_count(SCpnt)) { |
2103 | int prot_ret = prot_verify_write(SCpnt, lba, num, ei_lba); | 2107 | int prot_ret = prot_verify_write(SCpnt, lba, num, ei_lba); |
2104 | 2108 | ||
2105 | if (prot_ret) { | 2109 | if (prot_ret) { |
2110 | write_unlock_irqrestore(&atomic_rw, iflags); | ||
2106 | mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x10, prot_ret); | 2111 | mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x10, prot_ret); |
2107 | return illegal_condition_result; | 2112 | return illegal_condition_result; |
2108 | } | 2113 | } |
2109 | } | 2114 | } |
2110 | 2115 | ||
2111 | write_lock_irqsave(&atomic_rw, iflags); | ||
2112 | ret = do_device_access(SCpnt, devip, lba, num, 1); | 2116 | ret = do_device_access(SCpnt, devip, lba, num, 1); |
2113 | if (scsi_debug_lbp()) | 2117 | if (scsi_debug_lbp()) |
2114 | map_region(lba, num); | 2118 | map_region(lba, num); |
@@ -2187,6 +2191,7 @@ static int resp_unmap(struct scsi_cmnd * scmd, struct sdebug_dev_info * devip) | |||
2187 | struct unmap_block_desc *desc; | 2191 | struct unmap_block_desc *desc; |
2188 | unsigned int i, payload_len, descriptors; | 2192 | unsigned int i, payload_len, descriptors; |
2189 | int ret; | 2193 | int ret; |
2194 | unsigned long iflags; | ||
2190 | 2195 | ||
2191 | ret = check_readiness(scmd, 1, devip); | 2196 | ret = check_readiness(scmd, 1, devip); |
2192 | if (ret) | 2197 | if (ret) |
@@ -2208,6 +2213,8 @@ static int resp_unmap(struct scsi_cmnd * scmd, struct sdebug_dev_info * devip) | |||
2208 | 2213 | ||
2209 | desc = (void *)&buf[8]; | 2214 | desc = (void *)&buf[8]; |
2210 | 2215 | ||
2216 | write_lock_irqsave(&atomic_rw, iflags); | ||
2217 | |||
2211 | for (i = 0 ; i < descriptors ; i++) { | 2218 | for (i = 0 ; i < descriptors ; i++) { |
2212 | unsigned long long lba = get_unaligned_be64(&desc[i].lba); | 2219 | unsigned long long lba = get_unaligned_be64(&desc[i].lba); |
2213 | unsigned int num = get_unaligned_be32(&desc[i].blocks); | 2220 | 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) | |||
2222 | ret = 0; | 2229 | ret = 0; |
2223 | 2230 | ||
2224 | out: | 2231 | out: |
2232 | write_unlock_irqrestore(&atomic_rw, iflags); | ||
2225 | kfree(buf); | 2233 | kfree(buf); |
2226 | 2234 | ||
2227 | return ret; | 2235 | return ret; |