12 #include <sys/ioctl.h>
14 #include "mpath_pr_ioctl.h"
15 #include "mpath_persist.h"
16 #include "unaligned.h"
19 #include "structs.h" /* FILE_NAME_SIZE */
24 int prin_do_scsi_ioctl(char * dev, int rq_servact, struct prin_resp *resp, int noisy);
25 int mpath_translate_response (char * dev, struct sg_io_hdr io_hdr,
26 SenseData_t *Sensedata);
27 void dumpHex(const char* str, int len, int no_ascii);
28 int prout_do_scsi_ioctl( char * dev, int rq_servact, int rq_scope,
29 unsigned int rq_type, struct prout_param_descriptor *paramp, int noisy);
30 uint32_t format_transportids(struct prout_param_descriptor *paramp);
31 void convert_be32_to_cpu(uint32_t *num);
32 void convert_be16_to_cpu(uint16_t *num);
33 void decode_transport_id(struct prin_fulldescr *fdesc, unsigned char * p, int length);
34 int get_prin_length(int rq_servact);
35 int mpath_isLittleEndian(void);
37 unsigned int mpath_mx_alloc_len;
39 int prout_do_scsi_ioctl(char * dev, int rq_servact, int rq_scope,
40 unsigned int rq_type, struct prout_param_descriptor *paramp, int noisy)
43 int status, paramlen = 24, ret = 0;
46 SenseData_t Sensedata;
47 struct sg_io_hdr io_hdr;
48 char devname[FILE_NAME_SIZE];
51 snprintf(devname, FILE_NAME_SIZE, "/dev/%s",dev);
52 fd = open(devname, O_RDONLY);
54 condlog (1, "%s: unable to open device.", dev);
55 return MPATH_PR_FILE_ERROR;
58 unsigned char cdb[MPATH_PROUT_CMDLEN] =
59 {MPATH_PROUT_CMD, 0, 0, 0, 0, 0, 0, 0, 0, 0};
62 if (paramp->sa_flags & MPATH_F_SPEC_I_PT_MASK)
64 translen = format_transportids(paramp);
65 paramlen = 24 + translen;
71 cdb[1] = (unsigned char)(rq_servact & 0x1f);
72 cdb[2] = (((rq_scope & 0xf) << 4) | (rq_type & 0xf));
73 cdb[7] = (unsigned char)((paramlen >> 8) & 0xff);
74 cdb[8] = (unsigned char)(paramlen & 0xff);
77 condlog(4, "%s: rq_servact = %d", dev, rq_servact);
78 condlog(4, "%s: rq_scope = %d ", dev, rq_scope);
79 condlog(4, "%s: rq_type = %d ", dev, rq_type);
80 condlog(4, "%s: paramlen = %d", dev, paramlen);
84 condlog(4, "%s: Persistent Reservation OUT parameter:", dev);
85 dumpHex((const char *)paramp, paramlen,1);
88 memset(&Sensedata, 0, sizeof(SenseData_t));
89 memset(&io_hdr,0 , sizeof( struct sg_io_hdr));
90 io_hdr.interface_id = 'S';
91 io_hdr.cmd_len = MPATH_PROUT_CMDLEN;
93 io_hdr.sbp = (void *)&Sensedata;
94 io_hdr.mx_sb_len = sizeof (SenseData_t);
95 io_hdr.timeout = TIMEOUT;
98 io_hdr.dxferp = (void *)paramp;
99 io_hdr.dxfer_len = paramlen;
100 io_hdr.dxfer_direction = SG_DXFER_TO_DEV ;
103 io_hdr.dxfer_direction = SG_DXFER_NONE;
105 ret = ioctl(fd, SG_IO, &io_hdr);
108 condlog(0, "%s: ioctl failed %d", dev, ret);
113 condlog(4, "%s: Duration=%u (ms)", dev, io_hdr.duration);
115 status = mpath_translate_response(dev, io_hdr, &Sensedata);
116 condlog(3, "%s: status = %d", dev, status);
118 if (status == MPATH_PR_SENSE_UNIT_ATTENTION && (retry > 0))
121 condlog(3, "%s: retrying for Unit Attention. Remaining retries = %d",
126 if (((status == MPATH_PR_SENSE_NOT_READY )&& (Sensedata.ASC == 0x04)&&
127 (Sensedata.ASCQ == 0x07))&& (retry > 0))
131 condlog(3, "%s: retrying for sense 02/04/07."
132 " Remaining retries = %d", dev, retry);
141 * Helper macro to avoid overflow of prout_param_descriptor in
142 * format_transportids(). Data must not be written past
143 * MPATH_MAX_PARAM_LEN bytes from struct prout_param_descriptor.
145 #define check_overflow(ofs, n, start, label) \
148 offsetof(struct prout_param_descriptor, private_buffer) \
149 > MPATH_MAX_PARAM_LEN) \
156 uint32_t format_transportids(struct prout_param_descriptor *paramp)
158 unsigned int i = 0, len;
159 uint32_t buff_offset = 4;
160 memset(paramp->private_buffer, 0, sizeof(paramp->private_buffer));
161 for (i=0; i < paramp->num_transportid; i++ )
163 uint32_t start_offset = buff_offset;
165 check_overflow(buff_offset, 1, start_offset, end_loop);
166 paramp->private_buffer[buff_offset] = (uint8_t)((paramp->trnptid_list[i]->format_code & 0xff)|
167 (paramp->trnptid_list[i]->protocol_id & 0xff));
169 switch(paramp->trnptid_list[i]->protocol_id)
171 case MPATH_PROTOCOL_ID_FC:
172 check_overflow(buff_offset, 7 + 8 + 8,
173 start_offset, end_loop);
175 memcpy(¶mp->private_buffer[buff_offset], ¶mp->trnptid_list[i]->n_port_name, 8);
179 case MPATH_PROTOCOL_ID_SAS:
180 check_overflow(buff_offset, 3 + 12,
181 start_offset, end_loop);
183 memcpy(¶mp->private_buffer[buff_offset], ¶mp->trnptid_list[i]->sas_address, 8);
186 case MPATH_PROTOCOL_ID_ISCSI:
187 len = (paramp->trnptid_list[i]->iscsi_name[1] & 0xff)+2;
188 check_overflow(buff_offset, 1 + len,
189 start_offset, end_loop);
191 memcpy(¶mp->private_buffer[buff_offset], ¶mp->trnptid_list[i]->iscsi_name,len);
199 paramp->private_buffer[0] = (unsigned char)((buff_offset >> 24) & 0xff);
200 paramp->private_buffer[1] = (unsigned char)((buff_offset >> 16) & 0xff);
201 paramp->private_buffer[2] = (unsigned char)((buff_offset >> 8) & 0xff);
202 paramp->private_buffer[3] = (unsigned char)(buff_offset & 0xff);
207 static void mpath_format_readkeys(struct prin_resp *pr_buff)
209 convert_be32_to_cpu(&pr_buff->prin_descriptor.prin_readkeys.prgeneration);
210 convert_be32_to_cpu(&pr_buff->prin_descriptor.prin_readkeys.additional_length);
213 static void mpath_format_readresv(struct prin_resp *pr_buff)
216 convert_be32_to_cpu(&pr_buff->prin_descriptor.prin_readresv.prgeneration);
217 convert_be32_to_cpu(&pr_buff->prin_descriptor.prin_readresv.additional_length);
222 static void mpath_format_reportcapabilities(struct prin_resp *pr_buff)
224 convert_be16_to_cpu(&pr_buff->prin_descriptor.prin_readcap.length);
225 convert_be16_to_cpu(&pr_buff->prin_descriptor.prin_readcap.pr_type_mask);
230 static void mpath_format_readfullstatus(struct prin_resp *pr_buff)
233 uint32_t fdesc_count=0;
236 uint32_t additional_length, k, tid_len_len = 0;
237 char tempbuff[MPATH_MAX_PARAM_LEN];
238 struct prin_fulldescr fdesc;
239 static const unsigned int pbuf_size =
240 sizeof(pr_buff->prin_descriptor.prin_readfd.private_buffer);
242 convert_be32_to_cpu(&pr_buff->prin_descriptor.prin_readfd.prgeneration);
243 convert_be32_to_cpu(&pr_buff->prin_descriptor.prin_readfd.number_of_descriptor);
245 if (pr_buff->prin_descriptor.prin_readfd.number_of_descriptor == 0)
247 condlog(3, "No registration or reservation found.");
251 additional_length = pr_buff->prin_descriptor.prin_readfd.number_of_descriptor;
252 if (additional_length > pbuf_size) {
253 condlog(3, "PRIN length %u exceeds max length %d", additional_length,
258 memset(&fdesc, 0, sizeof(struct prin_fulldescr));
260 memcpy( tempbuff, pr_buff->prin_descriptor.prin_readfd.private_buffer,
262 memset(&pr_buff->prin_descriptor.prin_readfd.private_buffer, 0,
265 p =(unsigned char *)tempbuff;
266 ppbuff = (char *)pr_buff->prin_descriptor.prin_readfd.private_buffer;
268 for (k = 0; k < additional_length; k += num, p += num) {
269 memcpy(&fdesc.key, p, 8 );
271 fdesc.scope_type = p[13];
272 fdesc.rtpi = get_unaligned_be16(&p[18]);
274 tid_len_len = get_unaligned_be32(&p[20]);
275 if (tid_len_len + 24 + k > additional_length) {
277 "%s: corrupt PRIN response: status descriptor end %d exceeds length %d",
278 __func__, tid_len_len + k + 24,
280 tid_len_len = additional_length - k - 24;
284 decode_transport_id( &fdesc, &p[24], tid_len_len);
286 num = 24 + tid_len_len;
287 memcpy(ppbuff, &fdesc, sizeof(struct prin_fulldescr));
288 pr_buff->prin_descriptor.prin_readfd.descriptors[fdesc_count]= (struct prin_fulldescr *)ppbuff;
289 ppbuff += sizeof(struct prin_fulldescr);
293 pr_buff->prin_descriptor.prin_readfd.number_of_descriptor = fdesc_count;
299 decode_transport_id(struct prin_fulldescr *fdesc, unsigned char * p, int length)
303 for (k = 0, jump = 24; k < length; k += jump, p += jump) {
304 fdesc->trnptid.format_code = ((p[0] >> 6) & 0x3);
305 fdesc->trnptid.protocol_id = (p[0] & 0xf);
306 switch (fdesc->trnptid.protocol_id) {
307 case MPATH_PROTOCOL_ID_FC:
308 memcpy(&fdesc->trnptid.n_port_name, &p[8], 8);
311 case MPATH_PROTOCOL_ID_ISCSI:
312 num = get_unaligned_be16(&p[2]);
313 if (num >= sizeof(fdesc->trnptid.iscsi_name))
314 num = sizeof(fdesc->trnptid.iscsi_name);
315 memcpy(&fdesc->trnptid.iscsi_name, &p[4], num);
316 jump = (((num + 4) < 24) ? 24 : num + 4);
318 case MPATH_PROTOCOL_ID_SAS:
319 memcpy(&fdesc->trnptid.sas_address, &p[4], 8);
329 int prin_do_scsi_ioctl(char * dev, int rq_servact, struct prin_resp * resp, int noisy)
332 int ret, status, got, fd;
334 SenseData_t Sensedata;
335 int retry = MAXRETRY;
336 struct sg_io_hdr io_hdr;
337 char devname[FILE_NAME_SIZE];
338 unsigned char cdb[MPATH_PRIN_CMDLEN] =
339 {MPATH_PRIN_CMD, 0, 0, 0, 0, 0, 0, 0, 0, 0};
341 snprintf(devname, FILE_NAME_SIZE, "/dev/%s",dev);
342 fd = open(devname, O_RDONLY);
344 condlog(0, "%s: Unable to open device ", dev);
345 return MPATH_PR_FILE_ERROR;
348 if (mpath_mx_alloc_len)
349 mx_resp_len = mpath_mx_alloc_len;
351 mx_resp_len = get_prin_length(rq_servact);
353 if (mx_resp_len == 0) {
354 status = MPATH_PR_SYNTAX_ERROR;
358 cdb[1] = (unsigned char)(rq_servact & 0x1f);
359 cdb[7] = (unsigned char)((mx_resp_len >> 8) & 0xff);
360 cdb[8] = (unsigned char)(mx_resp_len & 0xff);
363 memset(&Sensedata, 0, sizeof(SenseData_t));
364 memset(&io_hdr,0 , sizeof( struct sg_io_hdr));
366 io_hdr.interface_id = 'S';
367 io_hdr.cmd_len = MPATH_PRIN_CMDLEN;
368 io_hdr.mx_sb_len = sizeof (SenseData_t);
369 io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
371 io_hdr.sbp = (void *)&Sensedata;
372 io_hdr.timeout = TIMEOUT;
376 io_hdr.dxfer_len = mx_resp_len;
377 io_hdr.dxferp = (void *)resp;
379 ret =ioctl(fd, SG_IO, &io_hdr);
381 condlog(0, "%s: IOCTL failed %d", dev, ret);
382 status = MPATH_PR_OTHER;
386 got = mx_resp_len - io_hdr.resid;
388 condlog(3, "%s: duration = %u (ms)", dev, io_hdr.duration);
389 condlog(4, "%s: persistent reservation in: requested %d bytes but got %d bytes)", dev, mx_resp_len, got);
391 status = mpath_translate_response(dev, io_hdr, &Sensedata);
393 if (status == MPATH_PR_SENSE_UNIT_ATTENTION && (retry > 0))
396 condlog(3, "%s: retrying for Unit Attention. Remaining retries = %d", dev, retry);
400 if (((status == MPATH_PR_SENSE_NOT_READY )&& (Sensedata.ASC == 0x04)&&
401 (Sensedata.ASCQ == 0x07))&& (retry > 0))
405 condlog(3, "%s: retrying for 02/04/07. Remaining retries = %d", dev, retry);
409 if (status != MPATH_PR_SUCCESS)
413 dumpHex((const char *)resp, got , 1);
418 case MPATH_PRIN_RKEY_SA :
419 mpath_format_readkeys(resp);
421 case MPATH_PRIN_RRES_SA :
422 mpath_format_readresv(resp);
424 case MPATH_PRIN_RCAP_SA :
425 mpath_format_reportcapabilities(resp);
427 case MPATH_PRIN_RFSTAT_SA :
428 mpath_format_readfullstatus(resp);
436 int mpath_translate_response (char * dev, struct sg_io_hdr io_hdr,
437 SenseData_t *Sensedata)
439 condlog(3, "%s: status driver:%02x host:%02x scsi:%02x", dev,
440 io_hdr.driver_status, io_hdr.host_status ,io_hdr.status);
441 io_hdr.status &= 0x7e;
442 if ((0 == io_hdr.status) &&
443 (0 == io_hdr.host_status) &&
444 (0 == io_hdr.driver_status))
445 return MPATH_PR_SUCCESS;
447 switch(io_hdr.status) {
450 case SAM_STAT_CHECK_CONDITION:
451 condlog(3, "%s: Sense_Key=%02x, ASC=%02x ASCQ=%02x",
452 dev, Sensedata->Sense_Key,
453 Sensedata->ASC, Sensedata->ASCQ);
454 switch(Sensedata->Sense_Key) {
456 return MPATH_PR_NO_SENSE;
457 case RECOVERED_ERROR:
458 return MPATH_PR_SUCCESS;
460 return MPATH_PR_SENSE_NOT_READY;
462 return MPATH_PR_SENSE_MEDIUM_ERROR;
464 return MPATH_PR_OTHER;
466 return MPATH_PR_SENSE_HARDWARE_ERROR;
467 case ILLEGAL_REQUEST:
468 return MPATH_PR_ILLEGAL_REQ;
470 return MPATH_PR_SENSE_UNIT_ATTENTION;
473 return MPATH_PR_OTHER;
474 case ABORTED_COMMAND:
475 return MPATH_PR_SENSE_ABORTED_COMMAND;
478 return MPATH_PR_OTHER;
480 case SAM_STAT_RESERVATION_CONFLICT:
481 return MPATH_PR_RESERV_CONFLICT;
484 return MPATH_PR_OTHER;
487 switch(io_hdr.host_status) {
491 return MPATH_PR_OTHER;
493 switch(io_hdr.driver_status)
498 return MPATH_PR_OTHER;
500 return MPATH_PR_SUCCESS;
503 void convert_be16_to_cpu(uint16_t *num)
505 *num = get_unaligned_be16(num);
508 void convert_be32_to_cpu(uint32_t *num)
510 *num = get_unaligned_be32(num);
514 dumpHex(const char* str, int len, int log)
516 const char * p = str;
519 const int bpstart = 5;
525 memset(buff, ' ', 80);
527 for (k = 0; k < len; k++) {
530 if (bpos == (bpstart + (9 * 3)))
532 sprintf(&buff[bpos], "%.2x", (int)(unsigned char)c);
533 buff[bpos + 2] = ' ';
534 if ((k > 0) && (0 == ((k + 1) % 16))) {
536 condlog(0, "%.76s" , buff);
538 printf("%.76s" , buff);
540 memset(buff, ' ', 80);
543 if (bpos > bpstart) {
544 buff[bpos + 2] = '\0';
546 condlog(0, "%s", buff);
548 printf("%s\n" , buff);
553 int get_prin_length(int rq_servact)
558 case MPATH_PRIN_RKEY_SA:
559 mx_resp_len = sizeof(struct prin_readdescr);
561 case MPATH_PRIN_RRES_SA :
562 mx_resp_len = sizeof(struct prin_resvdescr);
564 case MPATH_PRIN_RCAP_SA :
565 mx_resp_len = sizeof(struct prin_capdescr);
567 case MPATH_PRIN_RFSTAT_SA:
568 mx_resp_len = sizeof(struct print_fulldescr_list) + sizeof(struct prin_fulldescr *)*32;
571 condlog(0, "invalid service action, %d", rq_servact);
575 if (mx_resp_len > MPATH_MAX_PARAM_LEN)
576 mx_resp_len = MPATH_MAX_PARAM_LEN;