Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[SCSI] scsi_debug: support REPORT TARGET PORT GROUPS

This patch adds support for REPORT TARGET PORT GROUPS. This is used
eg for the multipathing priority callout to determine the path
priority.
With this patch multipath-tools can use the existing mpath_prio_alua
callout to exercise the path priority grouping.

Signed-off-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Douglas Gilbert <dougg@torque.net>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>

authored by

Hannes Reinecke and committed by
James Bottomley
5a09e398 cd00b7f5

+130 -14
+127 -14
drivers/scsi/scsi_debug.c
··· 52 52 #include "scsi_debug.h" 53 53 54 54 #define SCSI_DEBUG_VERSION "1.80" 55 - static const char * scsi_debug_version_date = "20060914"; 55 + static const char * scsi_debug_version_date = "20061018"; 56 56 57 57 /* Additional Sense Code (ASC) used */ 58 58 #define NO_ADDITIONAL_SENSE 0x0 ··· 254 254 struct sdebug_dev_info * devip); 255 255 static int resp_start_stop(struct scsi_cmnd * scp, 256 256 struct sdebug_dev_info * devip); 257 + static int resp_report_tgtpgs(struct scsi_cmnd * scp, 258 + struct sdebug_dev_info * devip); 257 259 static int resp_readcap(struct scsi_cmnd * SCpnt, 258 260 struct sdebug_dev_info * devip); 259 261 static int resp_readcap16(struct scsi_cmnd * SCpnt, ··· 289 287 static void __init init_all_queued(void); 290 288 static void stop_all_queued(void); 291 289 static int stop_queued_cmnd(struct scsi_cmnd * cmnd); 292 - static int inquiry_evpd_83(unsigned char * arr, int target_dev_id, 293 - int dev_id_num, const char * dev_id_str, 294 - int dev_id_str_len); 290 + static int inquiry_evpd_83(unsigned char * arr, int port_group_id, 291 + int target_dev_id, int dev_id_num, 292 + const char * dev_id_str, int dev_id_str_len); 295 293 static int inquiry_evpd_88(unsigned char * arr, int target_dev_id); 296 294 static int do_create_driverfs_files(void); 297 295 static void do_remove_driverfs_files(void); ··· 423 421 break; 424 422 } 425 423 errsts = resp_readcap16(SCpnt, devip); 424 + break; 425 + case MAINTENANCE_IN: 426 + if (MI_REPORT_TARGET_PGS != cmd[1]) { 427 + mk_sense_buffer(devip, ILLEGAL_REQUEST, 428 + INVALID_OPCODE, 0); 429 + errsts = check_condition_result; 430 + break; 431 + } 432 + errsts = resp_report_tgtpgs(SCpnt, devip); 426 433 break; 427 434 case READ_16: 428 435 case READ_12: ··· 676 665 static const char * inq_product_id = "scsi_debug "; 677 666 static const char * inq_product_rev = "0004"; 678 667 679 - static int inquiry_evpd_83(unsigned char * arr, int target_dev_id, 680 - int dev_id_num, const char * dev_id_str, 668 + static int inquiry_evpd_83(unsigned char * arr, int port_group_id, 669 + int target_dev_id, int dev_id_num, 670 + const char * dev_id_str, 681 671 int dev_id_str_len) 682 672 { 683 673 int num, port_a; ··· 732 720 arr[num++] = (port_a >> 16) & 0xff; 733 721 arr[num++] = (port_a >> 8) & 0xff; 734 722 arr[num++] = port_a & 0xff; 723 + /* NAA-5, Target port group identifier */ 724 + arr[num++] = 0x61; /* proto=sas, binary */ 725 + arr[num++] = 0x95; /* piv=1, target port group id */ 726 + arr[num++] = 0x0; 727 + arr[num++] = 0x4; 728 + arr[num++] = 0; 729 + arr[num++] = 0; 730 + arr[num++] = (port_group_id >> 8) & 0xff; 731 + arr[num++] = port_group_id & 0xff; 735 732 /* NAA-5, Target device identifier */ 736 733 arr[num++] = 0x61; /* proto=sas, binary */ 737 734 arr[num++] = 0xa3; /* piv=1, target device, naa */ ··· 949 928 struct sdebug_dev_info * devip) 950 929 { 951 930 unsigned char pq_pdt; 952 - unsigned char arr[SDEBUG_MAX_INQ_ARR_SZ]; 931 + unsigned char * arr; 953 932 unsigned char *cmd = (unsigned char *)scp->cmnd; 954 - int alloc_len, n; 933 + int alloc_len, n, ret; 955 934 956 935 alloc_len = (cmd[3] << 8) + cmd[4]; 957 - memset(arr, 0, SDEBUG_MAX_INQ_ARR_SZ); 936 + arr = kzalloc(SDEBUG_MAX_INQ_ARR_SZ, GFP_KERNEL); 958 937 if (devip->wlun) 959 938 pq_pdt = 0x1e; /* present, wlun */ 960 939 else if (scsi_debug_no_lun_0 && (0 == devip->lun)) ··· 965 944 if (0x2 & cmd[1]) { /* CMDDT bit set */ 966 945 mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 967 946 0); 947 + kfree(arr); 968 948 return check_condition_result; 969 949 } else if (0x1 & cmd[1]) { /* EVPD bit set */ 970 - int lu_id_num, target_dev_id, len; 950 + int lu_id_num, port_group_id, target_dev_id, len; 971 951 char lu_id_str[6]; 972 952 int host_no = devip->sdbg_host->shost->host_no; 973 953 954 + port_group_id = (((host_no + 1) & 0x7f) << 8) + 955 + (devip->channel & 0x7f); 974 956 if (0 == scsi_debug_vpd_use_hostno) 975 957 host_no = 0; 976 958 lu_id_num = devip->wlun ? -1 : (((host_no + 1) * 2000) + ··· 1001 977 memcpy(&arr[4], lu_id_str, len); 1002 978 } else if (0x83 == cmd[2]) { /* device identification */ 1003 979 arr[1] = cmd[2]; /*sanity */ 1004 - arr[3] = inquiry_evpd_83(&arr[4], target_dev_id, 1005 - lu_id_num, lu_id_str, len); 980 + arr[3] = inquiry_evpd_83(&arr[4], port_group_id, 981 + target_dev_id, lu_id_num, 982 + lu_id_str, len); 1006 983 } else if (0x84 == cmd[2]) { /* Software interface ident. */ 1007 984 arr[1] = cmd[2]; /*sanity */ 1008 985 arr[3] = inquiry_evpd_84(&arr[4]); ··· 1037 1012 /* Illegal request, invalid field in cdb */ 1038 1013 mk_sense_buffer(devip, ILLEGAL_REQUEST, 1039 1014 INVALID_FIELD_IN_CDB, 0); 1015 + kfree(arr); 1040 1016 return check_condition_result; 1041 1017 } 1042 1018 len = min(((arr[2] << 8) + arr[3]) + 4, alloc_len); 1043 - return fill_from_dev_buffer(scp, arr, 1019 + ret = fill_from_dev_buffer(scp, arr, 1044 1020 min(len, SDEBUG_MAX_INQ_ARR_SZ)); 1021 + kfree(arr); 1022 + return ret; 1045 1023 } 1046 1024 /* drops through here for a standard inquiry */ 1047 1025 arr[1] = DEV_REMOVEABLE(target) ? 0x80 : 0; /* Removable disk */ 1048 1026 arr[2] = scsi_debug_scsi_level; 1049 1027 arr[3] = 2; /* response_data_format==2 */ 1050 1028 arr[4] = SDEBUG_LONG_INQ_SZ - 5; 1029 + if (0 == scsi_debug_vpd_use_hostno) 1030 + arr[5] = 0x10; /* claim: implicit TGPS */ 1051 1031 arr[6] = 0x10; /* claim: MultiP */ 1052 1032 /* arr[6] |= 0x40; ... claim: EncServ (enclosure services) */ 1053 1033 arr[7] = 0xa; /* claim: LINKED + CMDQUE */ ··· 1069 1039 arr[n++] = 0x3; arr[n++] = 0x60; /* SSC-2 no version */ 1070 1040 } 1071 1041 arr[n++] = 0xc; arr[n++] = 0xf; /* SAS-1.1 rev 10 */ 1072 - return fill_from_dev_buffer(scp, arr, 1042 + ret = fill_from_dev_buffer(scp, arr, 1073 1043 min(alloc_len, SDEBUG_LONG_INQ_SZ)); 1044 + kfree(arr); 1045 + return ret; 1074 1046 } 1075 1047 1076 1048 static int resp_requests(struct scsi_cmnd * scp, ··· 1201 1169 arr[11] = SECT_SIZE_PER(target) & 0xff; 1202 1170 return fill_from_dev_buffer(scp, arr, 1203 1171 min(alloc_len, SDEBUG_READCAP16_ARR_SZ)); 1172 + } 1173 + 1174 + #define SDEBUG_MAX_TGTPGS_ARR_SZ 1412 1175 + 1176 + static int resp_report_tgtpgs(struct scsi_cmnd * scp, 1177 + struct sdebug_dev_info * devip) 1178 + { 1179 + unsigned char *cmd = (unsigned char *)scp->cmnd; 1180 + unsigned char * arr; 1181 + int host_no = devip->sdbg_host->shost->host_no; 1182 + int n, ret, alen, rlen; 1183 + int port_group_a, port_group_b, port_a, port_b; 1184 + 1185 + alen = ((cmd[6] << 24) + (cmd[7] << 16) + (cmd[8] << 8) 1186 + + cmd[9]); 1187 + 1188 + arr = kzalloc(SDEBUG_MAX_TGTPGS_ARR_SZ, GFP_KERNEL); 1189 + /* 1190 + * EVPD page 0x88 states we have two ports, one 1191 + * real and a fake port with no device connected. 1192 + * So we create two port groups with one port each 1193 + * and set the group with port B to unavailable. 1194 + */ 1195 + port_a = 0x1; /* relative port A */ 1196 + port_b = 0x2; /* relative port B */ 1197 + port_group_a = (((host_no + 1) & 0x7f) << 8) + 1198 + (devip->channel & 0x7f); 1199 + port_group_b = (((host_no + 1) & 0x7f) << 8) + 1200 + (devip->channel & 0x7f) + 0x80; 1201 + 1202 + /* 1203 + * The asymmetric access state is cycled according to the host_id. 1204 + */ 1205 + n = 4; 1206 + if (0 == scsi_debug_vpd_use_hostno) { 1207 + arr[n++] = host_no % 3; /* Asymm access state */ 1208 + arr[n++] = 0x0F; /* claim: all states are supported */ 1209 + } else { 1210 + arr[n++] = 0x0; /* Active/Optimized path */ 1211 + arr[n++] = 0x01; /* claim: only support active/optimized paths */ 1212 + } 1213 + arr[n++] = (port_group_a >> 8) & 0xff; 1214 + arr[n++] = port_group_a & 0xff; 1215 + arr[n++] = 0; /* Reserved */ 1216 + arr[n++] = 0; /* Status code */ 1217 + arr[n++] = 0; /* Vendor unique */ 1218 + arr[n++] = 0x1; /* One port per group */ 1219 + arr[n++] = 0; /* Reserved */ 1220 + arr[n++] = 0; /* Reserved */ 1221 + arr[n++] = (port_a >> 8) & 0xff; 1222 + arr[n++] = port_a & 0xff; 1223 + arr[n++] = 3; /* Port unavailable */ 1224 + arr[n++] = 0x08; /* claim: only unavailalbe paths are supported */ 1225 + arr[n++] = (port_group_b >> 8) & 0xff; 1226 + arr[n++] = port_group_b & 0xff; 1227 + arr[n++] = 0; /* Reserved */ 1228 + arr[n++] = 0; /* Status code */ 1229 + arr[n++] = 0; /* Vendor unique */ 1230 + arr[n++] = 0x1; /* One port per group */ 1231 + arr[n++] = 0; /* Reserved */ 1232 + arr[n++] = 0; /* Reserved */ 1233 + arr[n++] = (port_b >> 8) & 0xff; 1234 + arr[n++] = port_b & 0xff; 1235 + 1236 + rlen = n - 4; 1237 + arr[0] = (rlen >> 24) & 0xff; 1238 + arr[1] = (rlen >> 16) & 0xff; 1239 + arr[2] = (rlen >> 8) & 0xff; 1240 + arr[3] = rlen & 0xff; 1241 + 1242 + /* 1243 + * Return the smallest value of either 1244 + * - The allocated length 1245 + * - The constructed command length 1246 + * - The maximum array size 1247 + */ 1248 + rlen = min(alen,n); 1249 + ret = fill_from_dev_buffer(scp, arr, 1250 + min(rlen, SDEBUG_MAX_TGTPGS_ARR_SZ)); 1251 + kfree(arr); 1252 + return ret; 1204 1253 } 1205 1254 1206 1255 /* <<Following mode page info copied from ST318451LW>> */
+3
include/scsi/scsi.h
··· 97 97 #define PERSISTENT_RESERVE_IN 0x5e 98 98 #define PERSISTENT_RESERVE_OUT 0x5f 99 99 #define REPORT_LUNS 0xa0 100 + #define MAINTENANCE_IN 0xa3 100 101 #define MOVE_MEDIUM 0xa5 101 102 #define EXCHANGE_MEDIUM 0xa6 102 103 #define READ_12 0xa8 ··· 115 114 #define SERVICE_ACTION_IN 0x9e 116 115 /* values for service action in */ 117 116 #define SAI_READ_CAPACITY_16 0x10 117 + /* values for maintenance in */ 118 + #define MI_REPORT_TARGET_PGS 0x0a 118 119 119 120 /* Values for T10/04-262r7 */ 120 121 #define ATA_16 0x85 /* 16-byte pass-thru */