5050#include <scsi/scsi_host.h>
5151#include <scsi/scsicam.h>
5252#include <scsi/scsi_eh.h>
53+ #include <scsi/scsi_dbg.h>
5354
5455#include "sd.h"
5556#include "scsi_logging.h"
@@ -64,6 +65,7 @@ static const char * scsi_debug_version_date = "20070104";
6465#define PARAMETER_LIST_LENGTH_ERR 0x1a
6566#define INVALID_OPCODE 0x20
6667#define ADDR_OUT_OF_RANGE 0x21
68+ #define INVALID_COMMAND_OPCODE 0x20
6769#define INVALID_FIELD_IN_CDB 0x24
6870#define INVALID_FIELD_IN_PARAM_LIST 0x26
6971#define POWERON_RESET 0x29
@@ -180,7 +182,7 @@ static int sdebug_sectors_per; /* sectors per cylinder */
180182#define SDEBUG_SENSE_LEN 32
181183
182184#define SCSI_DEBUG_CANQUEUE 255
183- #define SCSI_DEBUG_MAX_CMD_LEN 16
185+ #define SCSI_DEBUG_MAX_CMD_LEN 32
184186
185187struct sdebug_dev_info {
186188 struct list_head dev_list ;
@@ -296,9 +298,25 @@ static void mk_sense_buffer(struct sdebug_dev_info *devip, int key,
296298}
297299
298300static 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 )
300303{
304+ * ei_lba = 0 ;
305+
301306 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+
302320 case WRITE_16 :
303321 case READ_16 :
304322 * lba = (u64 )cmd [9 ] | (u64 )cmd [8 ] << 8 |
@@ -1589,7 +1607,7 @@ static int do_device_access(struct scsi_cmnd *scmd,
15891607}
15901608
15911609static int prot_verify_read (struct scsi_cmnd * SCpnt , sector_t start_sec ,
1592- unsigned int sectors )
1610+ unsigned int sectors , u32 ei_lba )
15931611{
15941612 unsigned int i , resid ;
15951613 struct scatterlist * psgl ;
@@ -1636,13 +1654,23 @@ static int prot_verify_read(struct scsi_cmnd *SCpnt, sector_t start_sec,
16361654 return 0x01 ;
16371655 }
16381656
1639- if (scsi_debug_dif != SD_DIF_TYPE3_PROTECTION &&
1657+ if (scsi_debug_dif == SD_DIF_TYPE1_PROTECTION &&
16401658 be32_to_cpu (sdt [i ].ref_tag ) != (sector & 0xffffffff )) {
16411659 printk (KERN_ERR "%s: REF check failed on sector %lu\n" ,
16421660 __func__ , (unsigned long )sector );
16431661 dif_errors ++ ;
16441662 return 0x03 ;
16451663 }
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 ++ ;
16461674 }
16471675
16481676 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,
16701698}
16711699
16721700static 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 )
16741703{
16751704 unsigned long iflags ;
16761705 int ret ;
@@ -1699,7 +1728,7 @@ static int resp_read(struct scsi_cmnd *SCpnt, unsigned long long lba,
16991728
17001729 /* DIX + T10 DIF */
17011730 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 );
17031732
17041733 if (prot_ret ) {
17051734 mk_sense_buffer (devip , ABORTED_COMMAND , 0x10 , prot_ret );
@@ -1735,7 +1764,7 @@ void dump_sector(unsigned char *buf, int len)
17351764}
17361765
17371766static int prot_verify_write (struct scsi_cmnd * SCpnt , sector_t start_sec ,
1738- unsigned int sectors )
1767+ unsigned int sectors , u32 ei_lba )
17391768{
17401769 int i , j , ret ;
17411770 struct sd_dif_tuple * sdt ;
@@ -1749,11 +1778,6 @@ static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec,
17491778
17501779 sector = do_div (tmp_sec , sdebug_store_sectors );
17511780
1752- if (((SCpnt -> cmnd [1 ] >> 5 ) & 7 ) != 1 ) {
1753- printk (KERN_WARNING "scsi_debug: WRPROTECT != 1\n" );
1754- return 0 ;
1755- }
1756-
17571781 BUG_ON (scsi_sg_count (SCpnt ) == 0 );
17581782 BUG_ON (scsi_prot_sg_count (SCpnt ) == 0 );
17591783
@@ -1808,7 +1832,7 @@ static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec,
18081832 goto out ;
18091833 }
18101834
1811- if (scsi_debug_dif != SD_DIF_TYPE3_PROTECTION &&
1835+ if (scsi_debug_dif == SD_DIF_TYPE1_PROTECTION &&
18121836 be32_to_cpu (sdt -> ref_tag )
18131837 != (start_sec & 0xffffffff )) {
18141838 printk (KERN_ERR
@@ -1819,6 +1843,16 @@ static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec,
18191843 goto out ;
18201844 }
18211845
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+
18221856 /* Would be great to copy this in bigger
18231857 * chunks. However, for the sake of
18241858 * correctness we need to verify each sector
@@ -1832,6 +1866,7 @@ static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec,
18321866 sector = 0 ; /* Force wrap */
18331867
18341868 start_sec ++ ;
1869+ ei_lba ++ ;
18351870 daddr += scsi_debug_sector_size ;
18361871 ppage_offset += sizeof (struct sd_dif_tuple );
18371872 }
@@ -1853,7 +1888,8 @@ static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec,
18531888}
18541889
18551890static 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 )
18571893{
18581894 unsigned long iflags ;
18591895 int ret ;
@@ -1864,7 +1900,7 @@ static int resp_write(struct scsi_cmnd *SCpnt, unsigned long long lba,
18641900
18651901 /* DIX + T10 DIF */
18661902 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 );
18681904
18691905 if (prot_ret ) {
18701906 mk_sense_buffer (devip , ILLEGAL_REQUEST , 0x10 , prot_ret );
@@ -2872,11 +2908,12 @@ static int __init scsi_debug_init(void)
28722908
28732909 case SD_DIF_TYPE0_PROTECTION :
28742910 case SD_DIF_TYPE1_PROTECTION :
2911+ case SD_DIF_TYPE2_PROTECTION :
28752912 case SD_DIF_TYPE3_PROTECTION :
28762913 break ;
28772914
28782915 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" );
28802917 return - EINVAL ;
28812918 }
28822919
@@ -3121,6 +3158,7 @@ int scsi_debug_queuecommand(struct scsi_cmnd *SCpnt, done_funct_t done)
31213158 int len , k ;
31223159 unsigned int num ;
31233160 unsigned long long lba ;
3161+ u32 ei_lba ;
31243162 int errsts = 0 ;
31253163 int target = SCpnt -> device -> id ;
31263164 struct sdebug_dev_info * devip = NULL ;
@@ -3254,14 +3292,30 @@ int scsi_debug_queuecommand(struct scsi_cmnd *SCpnt, done_funct_t done)
32543292 case READ_16 :
32553293 case READ_12 :
32563294 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 */
32573310 case READ_6 :
3311+ read :
32583312 errsts = check_readiness (SCpnt , 0 , devip );
32593313 if (errsts )
32603314 break ;
32613315 if (scsi_debug_fake_rw )
32623316 break ;
3263- get_data_transfer_info (cmd , & lba , & num );
3264- errsts = resp_read (SCpnt , lba , num , devip );
3317+ get_data_transfer_info (cmd , & lba , & num , & ei_lba );
3318+ errsts = resp_read (SCpnt , lba , num , devip , ei_lba );
32653319 if (inj_recovered && (0 == errsts )) {
32663320 mk_sense_buffer (devip , RECOVERED_ERROR ,
32673321 THRESHOLD_EXCEEDED , 0 );
@@ -3288,14 +3342,30 @@ int scsi_debug_queuecommand(struct scsi_cmnd *SCpnt, done_funct_t done)
32883342 case WRITE_16 :
32893343 case WRITE_12 :
32903344 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 */
32913360 case WRITE_6 :
3361+ write :
32923362 errsts = check_readiness (SCpnt , 0 , devip );
32933363 if (errsts )
32943364 break ;
32953365 if (scsi_debug_fake_rw )
32963366 break ;
3297- get_data_transfer_info (cmd , & lba , & num );
3298- errsts = resp_write (SCpnt , lba , num , devip );
3367+ get_data_transfer_info (cmd , & lba , & num , & ei_lba );
3368+ errsts = resp_write (SCpnt , lba , num , devip , ei_lba );
32993369 if (inj_recovered && (0 == errsts )) {
33003370 mk_sense_buffer (devip , RECOVERED_ERROR ,
33013371 THRESHOLD_EXCEEDED , 0 );
@@ -3341,15 +3411,38 @@ int scsi_debug_queuecommand(struct scsi_cmnd *SCpnt, done_funct_t done)
33413411 break ;
33423412 if (scsi_debug_fake_rw )
33433413 break ;
3344- get_data_transfer_info (cmd , & lba , & num );
3345- errsts = resp_read (SCpnt , lba , num , devip );
3414+ get_data_transfer_info (cmd , & lba , & num , & ei_lba );
3415+ errsts = resp_read (SCpnt , lba , num , devip , ei_lba );
33463416 if (errsts )
33473417 break ;
3348- errsts = resp_write (SCpnt , lba , num , devip );
3418+ errsts = resp_write (SCpnt , lba , num , devip , ei_lba );
33493419 if (errsts )
33503420 break ;
33513421 errsts = resp_xdwriteread (SCpnt , lba , num , devip );
33523422 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+
33533446 default :
33543447 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts )
33553448 printk (KERN_INFO "scsi_debug: Opcode: 0x%x not "
0 commit comments