aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorMartin K. Petersen <martin.petersen@oracle.com>2009-09-18 17:33:03 -0400
committerJames Bottomley <James.Bottomley@suse.de>2009-10-02 10:47:17 -0400
commit395cef030c99349d238563095adc63ea72641192 (patch)
tree39c13437e8da8ef77805bba1e2a2d3e710f2bc48 /drivers/scsi
parent4e7392ec582cf06753b0969ca9ab959923e38493 (diff)
[SCSI] scsi_debug: Implement support for DIF Type 2
Add support for 32-byte READ/WRITE as well as DIF Type 2 protection. Reject protected 10/12/16 byte READ/WRITE commands when Type 2 is enabled. Verify Type 2 reference tag according to Expected Initial LBA in 32-byte CDB. Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> Acked-by: Douglas Gilbert <dgilbert@interlog.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/scsi_debug.c139
1 files changed, 116 insertions, 23 deletions
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index fb9af207d61d..c4103bef41b5 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -50,6 +50,7 @@
50#include <scsi/scsi_host.h> 50#include <scsi/scsi_host.h>
51#include <scsi/scsicam.h> 51#include <scsi/scsicam.h>
52#include <scsi/scsi_eh.h> 52#include <scsi/scsi_eh.h>
53#include <scsi/scsi_dbg.h>
53 54
54#include "sd.h" 55#include "sd.h"
55#include "scsi_logging.h" 56#include "scsi_logging.h"
@@ -64,6 +65,7 @@ static const char * scsi_debug_version_date = "20070104";
64#define PARAMETER_LIST_LENGTH_ERR 0x1a 65#define PARAMETER_LIST_LENGTH_ERR 0x1a
65#define INVALID_OPCODE 0x20 66#define INVALID_OPCODE 0x20
66#define ADDR_OUT_OF_RANGE 0x21 67#define ADDR_OUT_OF_RANGE 0x21
68#define INVALID_COMMAND_OPCODE 0x20
67#define INVALID_FIELD_IN_CDB 0x24 69#define INVALID_FIELD_IN_CDB 0x24
68#define INVALID_FIELD_IN_PARAM_LIST 0x26 70#define INVALID_FIELD_IN_PARAM_LIST 0x26
69#define POWERON_RESET 0x29 71#define POWERON_RESET 0x29
@@ -180,7 +182,7 @@ static int sdebug_sectors_per; /* sectors per cylinder */
180#define SDEBUG_SENSE_LEN 32 182#define SDEBUG_SENSE_LEN 32
181 183
182#define SCSI_DEBUG_CANQUEUE 255 184#define SCSI_DEBUG_CANQUEUE 255
183#define SCSI_DEBUG_MAX_CMD_LEN 16 185#define SCSI_DEBUG_MAX_CMD_LEN 32
184 186
185struct sdebug_dev_info { 187struct sdebug_dev_info {
186 struct list_head dev_list; 188 struct list_head dev_list;
@@ -296,9 +298,25 @@ static void mk_sense_buffer(struct sdebug_dev_info *devip, int key,
296} 298}
297 299
298static void get_data_transfer_info(unsigned char *cmd, 300static void get_data_transfer_info(unsigned char *cmd,
299 unsigned long long *lba, unsigned int *num) 301 unsigned long long *lba, unsigned int *num,
302 u32 *ei_lba)
300{ 303{
304 *ei_lba = 0;
305
301 switch (*cmd) { 306 switch (*cmd) {
307 case VARIABLE_LENGTH_CMD:
308 *lba = (u64)cmd[19] | (u64)cmd[18] << 8 |
309 (u64)cmd[17] << 16 | (u64)cmd[16] << 24 |
310 (u64)cmd[15] << 32 | (u64)cmd[14] << 40 |
311 (u64)cmd[13] << 48 | (u64)cmd[12] << 56;
312
313 *ei_lba = (u32)cmd[23] | (u32)cmd[22] << 8 |
314 (u32)cmd[21] << 16 | (u32)cmd[20] << 24;
315
316 *num = (u32)cmd[31] | (u32)cmd[30] << 8 | (u32)cmd[29] << 16 |
317 (u32)cmd[28] << 24;
318 break;
319
302 case WRITE_16: 320 case WRITE_16:
303 case READ_16: 321 case READ_16:
304 *lba = (u64)cmd[9] | (u64)cmd[8] << 8 | 322 *lba = (u64)cmd[9] | (u64)cmd[8] << 8 |
@@ -1589,7 +1607,7 @@ static int do_device_access(struct scsi_cmnd *scmd,
1589} 1607}
1590 1608
1591static int prot_verify_read(struct scsi_cmnd *SCpnt, sector_t start_sec, 1609static int prot_verify_read(struct scsi_cmnd *SCpnt, sector_t start_sec,
1592 unsigned int sectors) 1610 unsigned int sectors, u32 ei_lba)
1593{ 1611{
1594 unsigned int i, resid; 1612 unsigned int i, resid;
1595 struct scatterlist *psgl; 1613 struct scatterlist *psgl;
@@ -1636,13 +1654,23 @@ static int prot_verify_read(struct scsi_cmnd *SCpnt, sector_t start_sec,
1636 return 0x01; 1654 return 0x01;
1637 } 1655 }
1638 1656
1639 if (scsi_debug_dif != SD_DIF_TYPE3_PROTECTION && 1657 if (scsi_debug_dif == SD_DIF_TYPE1_PROTECTION &&
1640 be32_to_cpu(sdt[i].ref_tag) != (sector & 0xffffffff)) { 1658 be32_to_cpu(sdt[i].ref_tag) != (sector & 0xffffffff)) {
1641 printk(KERN_ERR "%s: REF check failed on sector %lu\n", 1659 printk(KERN_ERR "%s: REF check failed on sector %lu\n",
1642 __func__, (unsigned long)sector); 1660 __func__, (unsigned long)sector);
1643 dif_errors++; 1661 dif_errors++;
1644 return 0x03; 1662 return 0x03;
1645 } 1663 }
1664
1665 if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION &&
1666 be32_to_cpu(sdt[i].ref_tag) != ei_lba) {
1667 printk(KERN_ERR "%s: REF check failed on sector %lu\n",
1668 __func__, (unsigned long)sector);
1669 dif_errors++;
1670 return 0x03;
1671 }
1672
1673 ei_lba++;
1646 } 1674 }
1647 1675
1648 resid = sectors * 8; /* Bytes of protection data to copy into sgl */ 1676 resid = sectors * 8; /* Bytes of protection data to copy into sgl */
@@ -1670,7 +1698,8 @@ static int prot_verify_read(struct scsi_cmnd *SCpnt, sector_t start_sec,
1670} 1698}
1671 1699
1672static int resp_read(struct scsi_cmnd *SCpnt, unsigned long long lba, 1700static int resp_read(struct scsi_cmnd *SCpnt, unsigned long long lba,
1673 unsigned int num, struct sdebug_dev_info *devip) 1701 unsigned int num, struct sdebug_dev_info *devip,
1702 u32 ei_lba)
1674{ 1703{
1675 unsigned long iflags; 1704 unsigned long iflags;
1676 int ret; 1705 int ret;
@@ -1699,7 +1728,7 @@ static int resp_read(struct scsi_cmnd *SCpnt, unsigned long long lba,
1699 1728
1700 /* DIX + T10 DIF */ 1729 /* DIX + T10 DIF */
1701 if (scsi_debug_dix && scsi_prot_sg_count(SCpnt)) { 1730 if (scsi_debug_dix && scsi_prot_sg_count(SCpnt)) {
1702 int prot_ret = prot_verify_read(SCpnt, lba, num); 1731 int prot_ret = prot_verify_read(SCpnt, lba, num, ei_lba);
1703 1732
1704 if (prot_ret) { 1733 if (prot_ret) {
1705 mk_sense_buffer(devip, ABORTED_COMMAND, 0x10, prot_ret); 1734 mk_sense_buffer(devip, ABORTED_COMMAND, 0x10, prot_ret);
@@ -1735,7 +1764,7 @@ void dump_sector(unsigned char *buf, int len)
1735} 1764}
1736 1765
1737static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec, 1766static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec,
1738 unsigned int sectors) 1767 unsigned int sectors, u32 ei_lba)
1739{ 1768{
1740 int i, j, ret; 1769 int i, j, ret;
1741 struct sd_dif_tuple *sdt; 1770 struct sd_dif_tuple *sdt;
@@ -1749,11 +1778,6 @@ static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec,
1749 1778
1750 sector = do_div(tmp_sec, sdebug_store_sectors); 1779 sector = do_div(tmp_sec, sdebug_store_sectors);
1751 1780
1752 if (((SCpnt->cmnd[1] >> 5) & 7) != 1) {
1753 printk(KERN_WARNING "scsi_debug: WRPROTECT != 1\n");
1754 return 0;
1755 }
1756
1757 BUG_ON(scsi_sg_count(SCpnt) == 0); 1781 BUG_ON(scsi_sg_count(SCpnt) == 0);
1758 BUG_ON(scsi_prot_sg_count(SCpnt) == 0); 1782 BUG_ON(scsi_prot_sg_count(SCpnt) == 0);
1759 1783
@@ -1808,7 +1832,7 @@ static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec,
1808 goto out; 1832 goto out;
1809 } 1833 }
1810 1834
1811 if (scsi_debug_dif != SD_DIF_TYPE3_PROTECTION && 1835 if (scsi_debug_dif == SD_DIF_TYPE1_PROTECTION &&
1812 be32_to_cpu(sdt->ref_tag) 1836 be32_to_cpu(sdt->ref_tag)
1813 != (start_sec & 0xffffffff)) { 1837 != (start_sec & 0xffffffff)) {
1814 printk(KERN_ERR 1838 printk(KERN_ERR
@@ -1819,6 +1843,16 @@ static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec,
1819 goto out; 1843 goto out;
1820 } 1844 }
1821 1845
1846 if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION &&
1847 be32_to_cpu(sdt->ref_tag) != ei_lba) {
1848 printk(KERN_ERR
1849 "%s: REF check failed on sector %lu\n",
1850 __func__, (unsigned long)sector);
1851 ret = 0x03;
1852 dump_sector(daddr, scsi_debug_sector_size);
1853 goto out;
1854 }
1855
1822 /* Would be great to copy this in bigger 1856 /* Would be great to copy this in bigger
1823 * chunks. However, for the sake of 1857 * chunks. However, for the sake of
1824 * correctness we need to verify each sector 1858 * correctness we need to verify each sector
@@ -1832,6 +1866,7 @@ static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec,
1832 sector = 0; /* Force wrap */ 1866 sector = 0; /* Force wrap */
1833 1867
1834 start_sec++; 1868 start_sec++;
1869 ei_lba++;
1835 daddr += scsi_debug_sector_size; 1870 daddr += scsi_debug_sector_size;
1836 ppage_offset += sizeof(struct sd_dif_tuple); 1871 ppage_offset += sizeof(struct sd_dif_tuple);
1837 } 1872 }
@@ -1853,7 +1888,8 @@ out:
1853} 1888}
1854 1889
1855static int resp_write(struct scsi_cmnd *SCpnt, unsigned long long lba, 1890static int resp_write(struct scsi_cmnd *SCpnt, unsigned long long lba,
1856 unsigned int num, struct sdebug_dev_info *devip) 1891 unsigned int num, struct sdebug_dev_info *devip,
1892 u32 ei_lba)
1857{ 1893{
1858 unsigned long iflags; 1894 unsigned long iflags;
1859 int ret; 1895 int ret;
@@ -1864,7 +1900,7 @@ static int resp_write(struct scsi_cmnd *SCpnt, unsigned long long lba,
1864 1900
1865 /* DIX + T10 DIF */ 1901 /* DIX + T10 DIF */
1866 if (scsi_debug_dix && scsi_prot_sg_count(SCpnt)) { 1902 if (scsi_debug_dix && scsi_prot_sg_count(SCpnt)) {
1867 int prot_ret = prot_verify_write(SCpnt, lba, num); 1903 int prot_ret = prot_verify_write(SCpnt, lba, num, ei_lba);
1868 1904
1869 if (prot_ret) { 1905 if (prot_ret) {
1870 mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x10, prot_ret); 1906 mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x10, prot_ret);
@@ -2872,11 +2908,12 @@ static int __init scsi_debug_init(void)
2872 2908
2873 case SD_DIF_TYPE0_PROTECTION: 2909 case SD_DIF_TYPE0_PROTECTION:
2874 case SD_DIF_TYPE1_PROTECTION: 2910 case SD_DIF_TYPE1_PROTECTION:
2911 case SD_DIF_TYPE2_PROTECTION:
2875 case SD_DIF_TYPE3_PROTECTION: 2912 case SD_DIF_TYPE3_PROTECTION:
2876 break; 2913 break;
2877 2914
2878 default: 2915 default:
2879 printk(KERN_ERR "scsi_debug_init: dif must be 0, 1 or 3\n"); 2916 printk(KERN_ERR "scsi_debug_init: dif must be 0, 1, 2 or 3\n");
2880 return -EINVAL; 2917 return -EINVAL;
2881 } 2918 }
2882 2919
@@ -3121,6 +3158,7 @@ int scsi_debug_queuecommand(struct scsi_cmnd *SCpnt, done_funct_t done)
3121 int len, k; 3158 int len, k;
3122 unsigned int num; 3159 unsigned int num;
3123 unsigned long long lba; 3160 unsigned long long lba;
3161 u32 ei_lba;
3124 int errsts = 0; 3162 int errsts = 0;
3125 int target = SCpnt->device->id; 3163 int target = SCpnt->device->id;
3126 struct sdebug_dev_info *devip = NULL; 3164 struct sdebug_dev_info *devip = NULL;
@@ -3254,14 +3292,30 @@ int scsi_debug_queuecommand(struct scsi_cmnd *SCpnt, done_funct_t done)
3254 case READ_16: 3292 case READ_16:
3255 case READ_12: 3293 case READ_12:
3256 case READ_10: 3294 case READ_10:
3295 /* READ{10,12,16} and DIF Type 2 are natural enemies */
3296 if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION &&
3297 cmd[1] & 0xe0) {
3298 mk_sense_buffer(devip, ILLEGAL_REQUEST,
3299 INVALID_COMMAND_OPCODE, 0);
3300 errsts = check_condition_result;
3301 break;
3302 }
3303
3304 if ((scsi_debug_dif == SD_DIF_TYPE1_PROTECTION ||
3305 scsi_debug_dif == SD_DIF_TYPE3_PROTECTION) &&
3306 (cmd[1] & 0xe0) == 0)
3307 printk(KERN_ERR "Unprotected RD/WR to DIF device\n");
3308
3309 /* fall through */
3257 case READ_6: 3310 case READ_6:
3311read:
3258 errsts = check_readiness(SCpnt, 0, devip); 3312 errsts = check_readiness(SCpnt, 0, devip);
3259 if (errsts) 3313 if (errsts)
3260 break; 3314 break;
3261 if (scsi_debug_fake_rw) 3315 if (scsi_debug_fake_rw)
3262 break; 3316 break;
3263 get_data_transfer_info(cmd, &lba, &num); 3317 get_data_transfer_info(cmd, &lba, &num, &ei_lba);
3264 errsts = resp_read(SCpnt, lba, num, devip); 3318 errsts = resp_read(SCpnt, lba, num, devip, ei_lba);
3265 if (inj_recovered && (0 == errsts)) { 3319 if (inj_recovered && (0 == errsts)) {
3266 mk_sense_buffer(devip, RECOVERED_ERROR, 3320 mk_sense_buffer(devip, RECOVERED_ERROR,
3267 THRESHOLD_EXCEEDED, 0); 3321 THRESHOLD_EXCEEDED, 0);
@@ -3288,14 +3342,30 @@ int scsi_debug_queuecommand(struct scsi_cmnd *SCpnt, done_funct_t done)
3288 case WRITE_16: 3342 case WRITE_16:
3289 case WRITE_12: 3343 case WRITE_12:
3290 case WRITE_10: 3344 case WRITE_10:
3345 /* WRITE{10,12,16} and DIF Type 2 are natural enemies */
3346 if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION &&
3347 cmd[1] & 0xe0) {
3348 mk_sense_buffer(devip, ILLEGAL_REQUEST,
3349 INVALID_COMMAND_OPCODE, 0);
3350 errsts = check_condition_result;
3351 break;
3352 }
3353
3354 if ((scsi_debug_dif == SD_DIF_TYPE1_PROTECTION ||
3355 scsi_debug_dif == SD_DIF_TYPE3_PROTECTION) &&
3356 (cmd[1] & 0xe0) == 0)
3357 printk(KERN_ERR "Unprotected RD/WR to DIF device\n");
3358
3359 /* fall through */
3291 case WRITE_6: 3360 case WRITE_6:
3361write:
3292 errsts = check_readiness(SCpnt, 0, devip); 3362 errsts = check_readiness(SCpnt, 0, devip);
3293 if (errsts) 3363 if (errsts)
3294 break; 3364 break;
3295 if (scsi_debug_fake_rw) 3365 if (scsi_debug_fake_rw)
3296 break; 3366 break;
3297 get_data_transfer_info(cmd, &lba, &num); 3367 get_data_transfer_info(cmd, &lba, &num, &ei_lba);
3298 errsts = resp_write(SCpnt, lba, num, devip); 3368 errsts = resp_write(SCpnt, lba, num, devip, ei_lba);
3299 if (inj_recovered && (0 == errsts)) { 3369 if (inj_recovered && (0 == errsts)) {
3300 mk_sense_buffer(devip, RECOVERED_ERROR, 3370 mk_sense_buffer(devip, RECOVERED_ERROR,
3301 THRESHOLD_EXCEEDED, 0); 3371 THRESHOLD_EXCEEDED, 0);
@@ -3341,15 +3411,38 @@ int scsi_debug_queuecommand(struct scsi_cmnd *SCpnt, done_funct_t done)
3341 break; 3411 break;
3342 if (scsi_debug_fake_rw) 3412 if (scsi_debug_fake_rw)
3343 break; 3413 break;
3344 get_data_transfer_info(cmd, &lba, &num); 3414 get_data_transfer_info(cmd, &lba, &num, &ei_lba);
3345 errsts = resp_read(SCpnt, lba, num, devip); 3415 errsts = resp_read(SCpnt, lba, num, devip, ei_lba);
3346 if (errsts) 3416 if (errsts)
3347 break; 3417 break;
3348 errsts = resp_write(SCpnt, lba, num, devip); 3418 errsts = resp_write(SCpnt, lba, num, devip, ei_lba);
3349 if (errsts) 3419 if (errsts)
3350 break; 3420 break;
3351 errsts = resp_xdwriteread(SCpnt, lba, num, devip); 3421 errsts = resp_xdwriteread(SCpnt, lba, num, devip);
3352 break; 3422 break;
3423 case VARIABLE_LENGTH_CMD:
3424 if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION) {
3425
3426 if ((cmd[10] & 0xe0) == 0)
3427 printk(KERN_ERR
3428 "Unprotected RD/WR to DIF device\n");
3429
3430 if (cmd[9] == READ_32) {
3431 BUG_ON(SCpnt->cmd_len < 32);
3432 goto read;
3433 }
3434
3435 if (cmd[9] == WRITE_32) {
3436 BUG_ON(SCpnt->cmd_len < 32);
3437 goto write;
3438 }
3439 }
3440
3441 mk_sense_buffer(devip, ILLEGAL_REQUEST,
3442 INVALID_FIELD_IN_CDB, 0);
3443 errsts = check_condition_result;
3444 break;
3445
3353 default: 3446 default:
3354 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) 3447 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
3355 printk(KERN_INFO "scsi_debug: Opcode: 0x%x not " 3448 printk(KERN_INFO "scsi_debug: Opcode: 0x%x not "