11 #include <sys/ioctl.h>
14 #include "mpath_pr_ioctl.h"
15 #include "mpath_persist.h"
16 #include "unaligned.h"
20 #define FILE_NAME_SIZE 256
25 int prin_do_scsi_ioctl(char * dev, int rq_servact, struct prin_resp *resp, int noisy);
26 void mpath_format_readkeys(struct prin_resp *pr_buff, int len , int noisy);
27 void mpath_format_readfullstatus(struct prin_resp *pr_buff, int len, int noisy);
28 int mpath_translate_response (char * dev, struct sg_io_hdr io_hdr,
29 SenseData_t *Sensedata, int noisy);
30 void dumpHex(const char* str, int len, int no_ascii);
31 int prout_do_scsi_ioctl( char * dev, int rq_servact, int rq_scope,
32 unsigned int rq_type, struct prout_param_descriptor *paramp, int noisy);
33 uint32_t format_transportids(struct prout_param_descriptor *paramp);
34 void mpath_reverse_uint32_byteorder(uint32_t *num);
35 void mpath_reverse_uint16_byteorder(uint16_t *num);
36 void decode_transport_id(struct prin_fulldescr *fdesc, unsigned char * p, int length);
37 int get_prin_length(int rq_servact);
38 int mpath_isLittleEndian(void);
40 unsigned int mpath_mx_alloc_len;
42 int prout_do_scsi_ioctl(char * dev, int rq_servact, int rq_scope,
43 unsigned int rq_type, struct prout_param_descriptor *paramp, int noisy)
46 int status, paramlen = 24, ret = 0;
49 SenseData_t Sensedata;
50 struct sg_io_hdr io_hdr;
51 char devname[FILE_NAME_SIZE];
54 snprintf(devname, FILE_NAME_SIZE, "/dev/%s",dev);
55 fd = open(devname, O_WRONLY);
57 condlog (1, "%s: unable to open device.", dev);
58 return MPATH_PR_FILE_ERROR;
61 unsigned char cdb[MPATH_PROUT_CMDLEN] =
62 {MPATH_PROUT_CMD, 0, 0, 0, 0, 0, 0, 0, 0, 0};
65 if (paramp->sa_flags & MPATH_F_SPEC_I_PT_MASK)
67 translen = format_transportids(paramp);
68 paramlen = 24 + translen;
74 cdb[1] = (unsigned char)(rq_servact & 0x1f);
75 cdb[2] = (((rq_scope & 0xf) << 4) | (rq_type & 0xf));
76 cdb[7] = (unsigned char)((paramlen >> 8) & 0xff);
77 cdb[8] = (unsigned char)(paramlen & 0xff);
80 condlog(4, "%s: rq_servact = %d", dev, rq_servact);
81 condlog(4, "%s: rq_scope = %d ", dev, rq_scope);
82 condlog(4, "%s: rq_type = %d ", dev, rq_type);
83 condlog(4, "%s: paramlen = %d", dev, paramlen);
87 condlog(4, "%s: Persistent Reservation OUT parameter:", dev);
88 dumpHex((const char *)paramp, paramlen,1);
91 memset(&Sensedata, 0, sizeof(SenseData_t));
92 memset(&io_hdr,0 , sizeof( struct sg_io_hdr));
93 io_hdr.interface_id = 'S';
94 io_hdr.cmd_len = MPATH_PROUT_CMDLEN;
96 io_hdr.sbp = (void *)&Sensedata;
97 io_hdr.mx_sb_len = sizeof (SenseData_t);
98 io_hdr.timeout = TIMEOUT;
101 io_hdr.dxferp = (void *)paramp;
102 io_hdr.dxfer_len = paramlen;
103 io_hdr.dxfer_direction = SG_DXFER_TO_DEV ;
106 io_hdr.dxfer_direction = SG_DXFER_NONE;
108 ret = ioctl(fd, SG_IO, &io_hdr);
111 condlog(0, "%s: ioctl failed %d", dev, ret);
116 condlog(4, "%s: Duration=%u (ms)", dev, io_hdr.duration);
118 status = mpath_translate_response(dev, io_hdr, &Sensedata, noisy);
119 condlog(3, "%s: status = %d", dev, status);
121 if (status == MPATH_PR_SENSE_UNIT_ATTENTION && (retry > 0))
124 condlog(3, "%s: retrying for Unit Attention. Remaining retries = %d",
129 if (((status == MPATH_PR_SENSE_NOT_READY )&& (Sensedata.ASC == 0x04)&&
130 (Sensedata.ASCQ == 0x07))&& (retry > 0))
134 condlog(3, "%s: retrying for sense 02/04/07."
135 " Remaining retries = %d", dev, retry);
143 uint32_t format_transportids(struct prout_param_descriptor *paramp)
146 uint32_t buff_offset = 4;
147 memset(paramp->private_buffer, 0, MPATH_MAX_PARAM_LEN);
148 for (i=0; i < paramp->num_transportid; i++ )
150 paramp->private_buffer[buff_offset] = (uint8_t)((paramp->trnptid_list[i]->format_code & 0xff)|
151 (paramp->trnptid_list[i]->protocol_id & 0xff));
153 switch(paramp->trnptid_list[i]->protocol_id)
155 case MPATH_PROTOCOL_ID_FC:
157 memcpy(¶mp->private_buffer[buff_offset], ¶mp->trnptid_list[i]->n_port_name, 8);
161 case MPATH_PROTOCOL_ID_SAS:
163 memcpy(¶mp->private_buffer[buff_offset], ¶mp->trnptid_list[i]->sas_address, 8);
166 case MPATH_PROTOCOL_ID_ISCSI:
168 len = (paramp->trnptid_list[i]->iscsi_name[1] & 0xff)+2;
169 memcpy(¶mp->private_buffer[buff_offset], ¶mp->trnptid_list[i]->iscsi_name,len);
176 paramp->private_buffer[0] = (unsigned char)((buff_offset >> 24) & 0xff);
177 paramp->private_buffer[1] = (unsigned char)((buff_offset >> 16) & 0xff);
178 paramp->private_buffer[2] = (unsigned char)((buff_offset >> 8) & 0xff);
179 paramp->private_buffer[3] = (unsigned char)(buff_offset & 0xff);
184 void mpath_format_readkeys( struct prin_resp *pr_buff, int len, int noisy)
186 mpath_reverse_uint32_byteorder(&pr_buff->prin_descriptor.prin_readkeys.prgeneration);
187 mpath_reverse_uint32_byteorder(&pr_buff->prin_descriptor.prin_readkeys.additional_length);
190 void mpath_format_readresv(struct prin_resp *pr_buff, int len, int noisy)
193 mpath_reverse_uint32_byteorder(&pr_buff->prin_descriptor.prin_readkeys.prgeneration);
194 mpath_reverse_uint32_byteorder(&pr_buff->prin_descriptor.prin_readkeys.additional_length);
199 void mpath_format_reportcapabilities(struct prin_resp *pr_buff, int len, int noisy)
201 mpath_reverse_uint16_byteorder(&pr_buff->prin_descriptor.prin_readcap.length);
202 mpath_reverse_uint16_byteorder(&pr_buff->prin_descriptor.prin_readcap.pr_type_mask);
207 void mpath_format_readfullstatus(struct prin_resp *pr_buff, int len, int noisy)
209 int num, k, tid_len_len=0;
210 uint32_t fdesc_count=0;
213 uint32_t additional_length;
216 mpath_reverse_uint32_byteorder(&pr_buff->prin_descriptor.prin_readfd.prgeneration);
217 mpath_reverse_uint32_byteorder(&pr_buff->prin_descriptor.prin_readfd.number_of_descriptor);
219 if (pr_buff->prin_descriptor.prin_readfd.number_of_descriptor == 0)
221 condlog(3, "No registration or resrvation found.");
225 additional_length = pr_buff->prin_descriptor.prin_readfd.number_of_descriptor;
227 char tempbuff[MPATH_MAX_PARAM_LEN];
228 struct prin_fulldescr fdesc;
229 memset(&fdesc, 0, sizeof(struct prin_fulldescr));
231 memcpy( tempbuff, pr_buff->prin_descriptor.prin_readfd.private_buffer,MPATH_MAX_PARAM_LEN );
232 memset(&pr_buff->prin_descriptor.prin_readfd.private_buffer, 0, MPATH_MAX_PARAM_LEN);
234 p =(unsigned char *)tempbuff;
235 ppbuff = (char *)pr_buff->prin_descriptor.prin_readfd.private_buffer;
237 for (k = 0; k < additional_length; k += num, p += num) {
238 memcpy(&fdesc.key, p, 8 );
240 fdesc.scope_type = p[13];
241 fdesc.rtpi = get_unaligned_be16(&p[18]);
243 tid_len_len = get_unaligned_be32(&p[20]);
246 decode_transport_id( &fdesc, &p[24], tid_len_len);
248 num = 24 + tid_len_len;
249 memcpy(ppbuff, &fdesc, sizeof(struct prin_fulldescr));
250 pr_buff->prin_descriptor.prin_readfd.descriptors[fdesc_count]= (struct prin_fulldescr *)ppbuff;
251 ppbuff += sizeof(struct prin_fulldescr);
255 pr_buff->prin_descriptor.prin_readfd.number_of_descriptor = fdesc_count;
261 decode_transport_id(struct prin_fulldescr *fdesc, unsigned char * p, int length)
265 for (k = 0, jump = 24; k < length; k += jump, p += jump) {
266 fdesc->trnptid.format_code = ((p[0] >> 6) & 0x3);
267 fdesc->trnptid.protocol_id = (p[0] & 0xf);
268 switch (fdesc->trnptid.protocol_id) {
269 case MPATH_PROTOCOL_ID_FC:
270 memcpy(&fdesc->trnptid.n_port_name, &p[8], 8);
273 case MPATH_PROTOCOL_ID_ISCSI:
274 num = get_unaligned_be16(&p[2]);
275 memcpy(&fdesc->trnptid.iscsi_name, &p[4], num);
276 jump = (((num + 4) < 24) ? 24 : num + 4);
278 case MPATH_PROTOCOL_ID_SAS:
279 memcpy(&fdesc->trnptid.sas_address, &p[4], 8);
289 int prin_do_scsi_ioctl(char * dev, int rq_servact, struct prin_resp * resp, int noisy)
292 int ret, status, got, fd;
294 SenseData_t Sensedata;
295 int retry = MAXRETRY;
296 struct sg_io_hdr io_hdr;
297 char devname[FILE_NAME_SIZE];
298 unsigned char cdb[MPATH_PRIN_CMDLEN] =
299 {MPATH_PRIN_CMD, 0, 0, 0, 0, 0, 0, 0, 0, 0};
301 snprintf(devname, FILE_NAME_SIZE, "/dev/%s",dev);
302 fd = open(devname, O_WRONLY);
304 condlog(0, "%s: Unable to open device ", dev);
305 return MPATH_PR_FILE_ERROR;
308 if (mpath_mx_alloc_len)
309 mx_resp_len = mpath_mx_alloc_len;
311 mx_resp_len = get_prin_length(rq_servact);
313 if (mx_resp_len == 0) {
314 status = MPATH_PR_SYNTAX_ERROR;
318 cdb[1] = (unsigned char)(rq_servact & 0x1f);
319 cdb[7] = (unsigned char)((mx_resp_len >> 8) & 0xff);
320 cdb[8] = (unsigned char)(mx_resp_len & 0xff);
323 memset(&Sensedata, 0, sizeof(SenseData_t));
324 memset(&io_hdr,0 , sizeof( struct sg_io_hdr));
326 io_hdr.interface_id = 'S';
327 io_hdr.cmd_len = MPATH_PRIN_CMDLEN;
328 io_hdr.mx_sb_len = sizeof (SenseData_t);
329 io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
331 io_hdr.sbp = (void *)&Sensedata;
332 io_hdr.timeout = TIMEOUT;
336 io_hdr.dxfer_len = mx_resp_len;
337 io_hdr.dxferp = (void *)resp;
339 ret =ioctl(fd, SG_IO, &io_hdr);
341 condlog(0, "%s: IOCTL failed %d", dev, ret);
342 status = MPATH_PR_OTHER;
346 got = mx_resp_len - io_hdr.resid;
348 condlog(3, "%s: duration = %u (ms)", dev, io_hdr.duration);
349 condlog(4, "%s: persistent reservation in: requested %d bytes but got %d bytes)", dev, mx_resp_len, got);
351 status = mpath_translate_response(dev, io_hdr, &Sensedata, noisy);
353 if (status == MPATH_PR_SENSE_UNIT_ATTENTION && (retry > 0))
356 condlog(3, "%s: retrying for Unit Attention. Remaining retries = %d", dev, retry);
360 if (((status == MPATH_PR_SENSE_NOT_READY )&& (Sensedata.ASC == 0x04)&&
361 (Sensedata.ASCQ == 0x07))&& (retry > 0))
365 condlog(3, "%s: retrying for 02/04/07. Remaining retries = %d", dev, retry);
369 if (status != MPATH_PR_SUCCESS)
373 dumpHex((const char *)resp, got , 1);
378 case MPATH_PRIN_RKEY_SA :
379 mpath_format_readkeys(resp, got, noisy);
381 case MPATH_PRIN_RRES_SA :
382 mpath_format_readresv(resp, got, noisy);
384 case MPATH_PRIN_RCAP_SA :
385 mpath_format_reportcapabilities(resp, got, noisy);
387 case MPATH_PRIN_RFSTAT_SA :
388 mpath_format_readfullstatus(resp, got, noisy);
396 int mpath_translate_response (char * dev, struct sg_io_hdr io_hdr,
397 SenseData_t *Sensedata, int noisy)
399 condlog(3, "%s: status driver:%02x host:%02x scsi:%02x", dev,
400 io_hdr.driver_status, io_hdr.host_status ,io_hdr.status);
401 io_hdr.status &= 0x7e;
402 if ((0 == io_hdr.status) &&
403 (0 == io_hdr.host_status) &&
404 (0 == io_hdr.driver_status))
405 return MPATH_PR_SUCCESS;
407 switch(io_hdr.status) {
410 case SAM_STAT_CHECK_CONDITION:
411 condlog(3, "%s: Sense_Key=%02x, ASC=%02x ASCQ=%02x",
412 dev, Sensedata->Sense_Key,
413 Sensedata->ASC, Sensedata->ASCQ);
414 switch(Sensedata->Sense_Key) {
416 return MPATH_PR_NO_SENSE;
417 case RECOVERED_ERROR:
418 return MPATH_PR_SUCCESS;
420 return MPATH_PR_SENSE_NOT_READY;
422 return MPATH_PR_SENSE_MEDIUM_ERROR;
424 return MPATH_PR_OTHER;
426 return MPATH_PR_SENSE_HARDWARE_ERROR;
427 case ILLEGAL_REQUEST:
428 return MPATH_PR_ILLEGAL_REQ;
430 return MPATH_PR_SENSE_UNIT_ATTENTION;
433 return MPATH_PR_OTHER;
434 case ABORTED_COMMAND:
435 return MPATH_PR_SENSE_ABORTED_COMMAND;
438 return MPATH_PR_OTHER;
440 case SAM_STAT_RESERVATION_CONFLICT:
441 return MPATH_PR_RESERV_CONFLICT;
444 return MPATH_PR_OTHER;
447 switch(io_hdr.host_status) {
451 return MPATH_PR_OTHER;
453 switch(io_hdr.driver_status)
458 return MPATH_PR_OTHER;
460 return MPATH_PR_SUCCESS;
463 int mpath_isLittleEndian(void)
466 if(*(char *)&num == 1)
468 condlog(4, "Little-Endian");
472 condlog(4, "Big-Endian");
477 void mpath_reverse_uint16_byteorder(uint16_t *num)
479 uint16_t byte0, byte1;
481 byte0 = (*num & 0x000000FF) >> 0 ;
482 byte1 = (*num & 0x0000FF00) >> 8 ;
484 *num = ((byte0 << 8) | (byte1 << 0));
487 void mpath_reverse_uint32_byteorder(uint32_t *num)
489 uint32_t byte0, byte1, byte2, byte3;
491 byte0 = (*num & 0x000000FF) >> 0 ;
492 byte1 = (*num & 0x0000FF00) >> 8 ;
493 byte2 = (*num & 0x00FF0000) >> 16 ;
494 byte3 = (*num & 0xFF000000) >> 24 ;
496 *num = ((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | (byte3 << 0));
500 dumpHex(const char* str, int len, int log)
502 const char * p = str;
505 const int bpstart = 5;
511 memset(buff, ' ', 80);
513 for (k = 0; k < len; k++) {
516 if (bpos == (bpstart + (9 * 3)))
518 sprintf(&buff[bpos], "%.2x", (int)(unsigned char)c);
519 buff[bpos + 2] = ' ';
520 if ((k > 0) && (0 == ((k + 1) % 16))) {
522 condlog(0, "%.76s" , buff);
524 printf("%.76s" , buff);
526 memset(buff, ' ', 80);
529 if (bpos > bpstart) {
530 buff[bpos + 2] = '\0';
532 condlog(0, "%s", buff);
534 printf("%s\n" , buff);
539 int get_prin_length(int rq_servact)
544 case MPATH_PRIN_RKEY_SA:
545 mx_resp_len = sizeof(struct prin_readdescr);
547 case MPATH_PRIN_RRES_SA :
548 mx_resp_len = sizeof(struct prin_resvdescr);
550 case MPATH_PRIN_RCAP_SA :
551 mx_resp_len = sizeof(struct prin_capdescr);
553 case MPATH_PRIN_RFSTAT_SA:
554 mx_resp_len = sizeof(struct print_fulldescr_list) + sizeof(struct prin_fulldescr *)*32;
557 condlog(0, "invalid service action, %d", rq_servact);