aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/scsi_debug.c
diff options
context:
space:
mode:
authorMartin K. Petersen <martin.petersen@oracle.com>2010-08-19 11:49:00 -0400
committerJames Bottomley <James.Bottomley@suse.de>2010-09-09 16:34:40 -0400
commit6014759c929b4ce8c068810b8d05f31969df5897 (patch)
tree3b0e9dee2dcc17a63367e04bd965e9262a288777 /drivers/scsi/scsi_debug.c
parent47259658ed9fad837541b738f9375d38022daa14 (diff)
[SCSI] scsi_debug: Update thin provisioning support
The previous thin provisioning support was not very user friendly because it depended on all the relevant options being set on the command line. Implement support for the Thin Provisioning VPD page from SBC3 r24 and add module options for TPU (UNMAP) and TPWS (WRITE SAME (16) with UNMAP bit). This allows us to have sane default and to enable thin provisioning with a simple tpu=1 or tpws=1 on the command line depending on whether we want UNMAP or WRITE SAME behavior. 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/scsi_debug.c')
-rw-r--r--drivers/scsi/scsi_debug.c100
1 files changed, 69 insertions, 31 deletions
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index b02bdc6c2cd..06329d47b38 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -109,10 +109,12 @@ static const char * scsi_debug_version_date = "20100324";
109#define DEF_PHYSBLK_EXP 0 109#define DEF_PHYSBLK_EXP 0
110#define DEF_LOWEST_ALIGNED 0 110#define DEF_LOWEST_ALIGNED 0
111#define DEF_OPT_BLKS 64 111#define DEF_OPT_BLKS 64
112#define DEF_UNMAP_MAX_BLOCKS 0 112#define DEF_UNMAP_MAX_BLOCKS 0xFFFFFFFF
113#define DEF_UNMAP_MAX_DESC 0 113#define DEF_UNMAP_MAX_DESC 256
114#define DEF_UNMAP_GRANULARITY 0 114#define DEF_UNMAP_GRANULARITY 1
115#define DEF_UNMAP_ALIGNMENT 0 115#define DEF_UNMAP_ALIGNMENT 0
116#define DEF_TPWS 0
117#define DEF_TPU 0
116 118
117/* bit mask values for scsi_debug_opts */ 119/* bit mask values for scsi_debug_opts */
118#define SCSI_DEBUG_OPT_NOISE 1 120#define SCSI_DEBUG_OPT_NOISE 1
@@ -177,10 +179,12 @@ static int scsi_debug_ato = DEF_ATO;
177static int scsi_debug_physblk_exp = DEF_PHYSBLK_EXP; 179static int scsi_debug_physblk_exp = DEF_PHYSBLK_EXP;
178static int scsi_debug_lowest_aligned = DEF_LOWEST_ALIGNED; 180static int scsi_debug_lowest_aligned = DEF_LOWEST_ALIGNED;
179static int scsi_debug_opt_blks = DEF_OPT_BLKS; 181static int scsi_debug_opt_blks = DEF_OPT_BLKS;
180static int scsi_debug_unmap_max_desc = DEF_UNMAP_MAX_DESC; 182static unsigned int scsi_debug_unmap_max_desc = DEF_UNMAP_MAX_DESC;
181static int scsi_debug_unmap_max_blocks = DEF_UNMAP_MAX_BLOCKS; 183static unsigned int scsi_debug_unmap_max_blocks = DEF_UNMAP_MAX_BLOCKS;
182static int scsi_debug_unmap_granularity = DEF_UNMAP_GRANULARITY; 184static unsigned int scsi_debug_unmap_granularity = DEF_UNMAP_GRANULARITY;
183static int scsi_debug_unmap_alignment = DEF_UNMAP_ALIGNMENT; 185static unsigned int scsi_debug_unmap_alignment = DEF_UNMAP_ALIGNMENT;
186static unsigned int scsi_debug_tpws = DEF_TPWS;
187static unsigned int scsi_debug_tpu = DEF_TPU;
184 188
185static int scsi_debug_cmnd_count = 0; 189static int scsi_debug_cmnd_count = 0;
186 190
@@ -723,16 +727,9 @@ static int inquiry_evpd_b0(unsigned char * arr)
723 /* Optimal Transfer Length */ 727 /* Optimal Transfer Length */
724 put_unaligned_be32(scsi_debug_opt_blks, &arr[8]); 728 put_unaligned_be32(scsi_debug_opt_blks, &arr[8]);
725 729
726 if (scsi_debug_unmap_max_desc) { 730 if (scsi_debug_tpu) {
727 unsigned int blocks;
728
729 if (scsi_debug_unmap_max_blocks)
730 blocks = scsi_debug_unmap_max_blocks;
731 else
732 blocks = 0xffffffff;
733
734 /* Maximum Unmap LBA Count */ 731 /* Maximum Unmap LBA Count */
735 put_unaligned_be32(blocks, &arr[16]); 732 put_unaligned_be32(scsi_debug_unmap_max_blocks, &arr[16]);
736 733
737 /* Maximum Unmap Block Descriptor Count */ 734 /* Maximum Unmap Block Descriptor Count */
738 put_unaligned_be32(scsi_debug_unmap_max_desc, &arr[20]); 735 put_unaligned_be32(scsi_debug_unmap_max_desc, &arr[20]);
@@ -745,10 +742,9 @@ static int inquiry_evpd_b0(unsigned char * arr)
745 } 742 }
746 743
747 /* Optimal Unmap Granularity */ 744 /* Optimal Unmap Granularity */
748 if (scsi_debug_unmap_granularity) { 745 put_unaligned_be32(scsi_debug_unmap_granularity, &arr[24]);
749 put_unaligned_be32(scsi_debug_unmap_granularity, &arr[24]); 746
750 return 0x3c; /* Mandatory page length for thin provisioning */ 747 return 0x3c; /* Mandatory page length for thin provisioning */
751 }
752 748
753 return sizeof(vpdb0_data); 749 return sizeof(vpdb0_data);
754} 750}
@@ -765,6 +761,21 @@ static int inquiry_evpd_b1(unsigned char *arr)
765 return 0x3c; 761 return 0x3c;
766} 762}
767 763
764/* Thin provisioning VPD page (SBC-3) */
765static int inquiry_evpd_b2(unsigned char *arr)
766{
767 memset(arr, 0, 0x8);
768 arr[0] = 0; /* threshold exponent */
769
770 if (scsi_debug_tpu)
771 arr[1] = 1 << 7;
772
773 if (scsi_debug_tpws)
774 arr[1] |= 1 << 6;
775
776 return 0x8;
777}
778
768#define SDEBUG_LONG_INQ_SZ 96 779#define SDEBUG_LONG_INQ_SZ 96
769#define SDEBUG_MAX_INQ_ARR_SZ 584 780#define SDEBUG_MAX_INQ_ARR_SZ 584
770 781
@@ -820,6 +831,7 @@ static int resp_inquiry(struct scsi_cmnd * scp, int target,
820 arr[n++] = 0x89; /* ATA information */ 831 arr[n++] = 0x89; /* ATA information */
821 arr[n++] = 0xb0; /* Block limits (SBC) */ 832 arr[n++] = 0xb0; /* Block limits (SBC) */
822 arr[n++] = 0xb1; /* Block characteristics (SBC) */ 833 arr[n++] = 0xb1; /* Block characteristics (SBC) */
834 arr[n++] = 0xb2; /* Thin provisioning (SBC) */
823 arr[3] = n - 4; /* number of supported VPD pages */ 835 arr[3] = n - 4; /* number of supported VPD pages */
824 } else if (0x80 == cmd[2]) { /* unit serial number */ 836 } else if (0x80 == cmd[2]) { /* unit serial number */
825 arr[1] = cmd[2]; /*sanity */ 837 arr[1] = cmd[2]; /*sanity */
@@ -867,6 +879,9 @@ static int resp_inquiry(struct scsi_cmnd * scp, int target,
867 } else if (0xb1 == cmd[2]) { /* Block characteristics (SBC) */ 879 } else if (0xb1 == cmd[2]) { /* Block characteristics (SBC) */
868 arr[1] = cmd[2]; /*sanity */ 880 arr[1] = cmd[2]; /*sanity */
869 arr[3] = inquiry_evpd_b1(&arr[4]); 881 arr[3] = inquiry_evpd_b1(&arr[4]);
882 } else if (0xb2 == cmd[2]) { /* Thin provisioning (SBC) */
883 arr[1] = cmd[2]; /*sanity */
884 arr[3] = inquiry_evpd_b2(&arr[4]);
870 } else { 885 } else {
871 /* Illegal request, invalid field in cdb */ 886 /* Illegal request, invalid field in cdb */
872 mk_sense_buffer(devip, ILLEGAL_REQUEST, 887 mk_sense_buffer(devip, ILLEGAL_REQUEST,
@@ -1038,7 +1053,7 @@ static int resp_readcap16(struct scsi_cmnd * scp,
1038 arr[13] = scsi_debug_physblk_exp & 0xf; 1053 arr[13] = scsi_debug_physblk_exp & 0xf;
1039 arr[14] = (scsi_debug_lowest_aligned >> 8) & 0x3f; 1054 arr[14] = (scsi_debug_lowest_aligned >> 8) & 0x3f;
1040 1055
1041 if (scsi_debug_unmap_granularity) 1056 if (scsi_debug_tpu || scsi_debug_tpws)
1042 arr[14] |= 0x80; /* TPE */ 1057 arr[14] |= 0x80; /* TPE */
1043 1058
1044 arr[15] = scsi_debug_lowest_aligned & 0xff; 1059 arr[15] = scsi_debug_lowest_aligned & 0xff;
@@ -2708,6 +2723,8 @@ module_param_named(unmap_max_blocks, scsi_debug_unmap_max_blocks, int, S_IRUGO);
2708module_param_named(unmap_max_desc, scsi_debug_unmap_max_desc, int, S_IRUGO); 2723module_param_named(unmap_max_desc, scsi_debug_unmap_max_desc, int, S_IRUGO);
2709module_param_named(unmap_granularity, scsi_debug_unmap_granularity, int, S_IRUGO); 2724module_param_named(unmap_granularity, scsi_debug_unmap_granularity, int, S_IRUGO);
2710module_param_named(unmap_alignment, scsi_debug_unmap_alignment, int, S_IRUGO); 2725module_param_named(unmap_alignment, scsi_debug_unmap_alignment, int, S_IRUGO);
2726module_param_named(tpu, scsi_debug_tpu, int, S_IRUGO);
2727module_param_named(tpws, scsi_debug_tpws, int, S_IRUGO);
2711 2728
2712MODULE_AUTHOR("Eric Youngdale + Douglas Gilbert"); 2729MODULE_AUTHOR("Eric Youngdale + Douglas Gilbert");
2713MODULE_DESCRIPTION("SCSI debug adapter driver"); 2730MODULE_DESCRIPTION("SCSI debug adapter driver");
@@ -2739,10 +2756,12 @@ MODULE_PARM_DESC(dix, "data integrity extensions mask (def=0)");
2739MODULE_PARM_DESC(dif, "data integrity field type: 0-3 (def=0)"); 2756MODULE_PARM_DESC(dif, "data integrity field type: 0-3 (def=0)");
2740MODULE_PARM_DESC(guard, "protection checksum: 0=crc, 1=ip (def=0)"); 2757MODULE_PARM_DESC(guard, "protection checksum: 0=crc, 1=ip (def=0)");
2741MODULE_PARM_DESC(ato, "application tag ownership: 0=disk 1=host (def=1)"); 2758MODULE_PARM_DESC(ato, "application tag ownership: 0=disk 1=host (def=1)");
2742MODULE_PARM_DESC(unmap_max_blocks, "max # of blocks can be unmapped in one cmd (def=0)"); 2759MODULE_PARM_DESC(unmap_max_blocks, "max # of blocks can be unmapped in one cmd (def=0xffffffff)");
2743MODULE_PARM_DESC(unmap_max_desc, "max # of ranges that can be unmapped in one cmd (def=0)"); 2760MODULE_PARM_DESC(unmap_max_desc, "max # of ranges that can be unmapped in one cmd (def=256)");
2744MODULE_PARM_DESC(unmap_granularity, "thin provisioning granularity in blocks (def=0)"); 2761MODULE_PARM_DESC(unmap_granularity, "thin provisioning granularity in blocks (def=1)");
2745MODULE_PARM_DESC(unmap_alignment, "lowest aligned thin provisioning lba (def=0)"); 2762MODULE_PARM_DESC(unmap_alignment, "lowest aligned thin provisioning lba (def=0)");
2763MODULE_PARM_DESC(tpu, "enable TP, support UNMAP command (def=0)");
2764MODULE_PARM_DESC(tpws, "enable TP, support WRITE SAME(16) with UNMAP bit (def=0)");
2746 2765
2747static char sdebug_info[256]; 2766static char sdebug_info[256];
2748 2767
@@ -3130,7 +3149,7 @@ static ssize_t sdebug_map_show(struct device_driver *ddp, char *buf)
3130{ 3149{
3131 ssize_t count; 3150 ssize_t count;
3132 3151
3133 if (scsi_debug_unmap_granularity == 0) 3152 if (scsi_debug_tpu == 0 && scsi_debug_tpws == 0)
3134 return scnprintf(buf, PAGE_SIZE, "0-%u\n", 3153 return scnprintf(buf, PAGE_SIZE, "0-%u\n",
3135 sdebug_store_sectors); 3154 sdebug_store_sectors);
3136 3155
@@ -3322,10 +3341,21 @@ static int __init scsi_debug_init(void)
3322 memset(dif_storep, 0xff, dif_size); 3341 memset(dif_storep, 0xff, dif_size);
3323 } 3342 }
3324 3343
3325 if (scsi_debug_unmap_granularity) { 3344 /* Thin Provisioning */
3345 if (scsi_debug_tpu || scsi_debug_tpws) {
3326 unsigned int map_bytes; 3346 unsigned int map_bytes;
3327 3347
3328 if (scsi_debug_unmap_granularity < scsi_debug_unmap_alignment) { 3348 scsi_debug_unmap_max_blocks =
3349 clamp(scsi_debug_unmap_max_blocks, 0U, 0xffffffffU);
3350
3351 scsi_debug_unmap_max_desc =
3352 clamp(scsi_debug_unmap_max_desc, 0U, 256U);
3353
3354 scsi_debug_unmap_granularity =
3355 clamp(scsi_debug_unmap_granularity, 1U, 0xffffffffU);
3356
3357 if (scsi_debug_unmap_alignment &&
3358 scsi_debug_unmap_granularity < scsi_debug_unmap_alignment) {
3329 printk(KERN_ERR 3359 printk(KERN_ERR
3330 "%s: ERR: unmap_granularity < unmap_alignment\n", 3360 "%s: ERR: unmap_granularity < unmap_alignment\n",
3331 __func__); 3361 __func__);
@@ -3642,7 +3672,7 @@ int scsi_debug_queuecommand(struct scsi_cmnd *SCpnt, done_funct_t done)
3642 errsts = resp_readcap16(SCpnt, devip); 3672 errsts = resp_readcap16(SCpnt, devip);
3643 else if (cmd[1] == SAI_GET_LBA_STATUS) { 3673 else if (cmd[1] == SAI_GET_LBA_STATUS) {
3644 3674
3645 if (scsi_debug_unmap_max_desc == 0) { 3675 if (scsi_debug_tpu == 0 && scsi_debug_tpws == 0) {
3646 mk_sense_buffer(devip, ILLEGAL_REQUEST, 3676 mk_sense_buffer(devip, ILLEGAL_REQUEST,
3647 INVALID_COMMAND_OPCODE, 0); 3677 INVALID_COMMAND_OPCODE, 0);
3648 errsts = check_condition_result; 3678 errsts = check_condition_result;
@@ -3753,8 +3783,16 @@ write:
3753 } 3783 }
3754 break; 3784 break;
3755 case WRITE_SAME_16: 3785 case WRITE_SAME_16:
3756 if (cmd[1] & 0x8) 3786 if (cmd[1] & 0x8) {
3757 unmap = 1; 3787 if (scsi_debug_tpws == 0) {
3788 mk_sense_buffer(devip, ILLEGAL_REQUEST,
3789 INVALID_FIELD_IN_CDB, 0);
3790 errsts = check_condition_result;
3791 } else
3792 unmap = 1;
3793 }
3794 if (errsts)
3795 break;
3758 /* fall through */ 3796 /* fall through */
3759 case WRITE_SAME: 3797 case WRITE_SAME:
3760 errsts = check_readiness(SCpnt, 0, devip); 3798 errsts = check_readiness(SCpnt, 0, devip);
@@ -3768,7 +3806,7 @@ write:
3768 if (errsts) 3806 if (errsts)
3769 break; 3807 break;
3770 3808
3771 if (scsi_debug_unmap_max_desc == 0) { 3809 if (scsi_debug_unmap_max_desc == 0 || scsi_debug_tpu == 0) {
3772 mk_sense_buffer(devip, ILLEGAL_REQUEST, 3810 mk_sense_buffer(devip, ILLEGAL_REQUEST,
3773 INVALID_COMMAND_OPCODE, 0); 3811 INVALID_COMMAND_OPCODE, 0);
3774 errsts = check_condition_result; 3812 errsts = check_condition_result;