2 * Copyright (c) 2005 Christophe Varoqui
11 #include <sys/ioctl.h>
14 #include "path_state.h"
17 #include "../libmultipath/sg_include.h"
20 #define INQUIRY_CMDLEN 6
21 #define INQUIRY_CMD 0x12
22 #define SENSE_BUFF_LEN 32
23 #define DEF_TIMEOUT 60000
24 #define SCSI_CHECK_CONDITION 0x2
25 #define SCSI_COMMAND_TERMINATED 0x22
26 #define SG_ERR_DRIVER_SENSE 0x08
27 #define RECOVERED_ERROR 0x01
28 #define MX_ALLOC_LEN 255
29 #define HEAVY_CHECK_COUNT 10
31 #define MSG_HP_SW_UP "hp_sw checker reports path is up"
32 #define MSG_HP_SW_DOWN "hp_sw checker reports path is down"
33 #define MSG_HP_SW_GHOST "hp_sw checker reports path is ghost"
35 struct sw_checker_context {
40 do_inq(int sg_fd, int cmddt, int evpd, unsigned int pg_op,
41 void *resp, int mx_resp_len, int noisy)
43 unsigned char inqCmdBlk[INQUIRY_CMDLEN] =
44 { INQUIRY_CMD, 0, 0, 0, 0, 0 };
45 unsigned char sense_b[SENSE_BUFF_LEN];
46 struct sg_io_hdr io_hdr;
52 inqCmdBlk[2] = (unsigned char) pg_op;
53 inqCmdBlk[3] = (unsigned char)((mx_resp_len >> 8) & 0xff);
54 inqCmdBlk[4] = (unsigned char) (mx_resp_len & 0xff);
55 memset(&io_hdr, 0, sizeof (struct sg_io_hdr));
56 io_hdr.interface_id = 'S';
57 io_hdr.cmd_len = sizeof (inqCmdBlk);
58 io_hdr.mx_sb_len = sizeof (sense_b);
59 io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
60 io_hdr.dxfer_len = mx_resp_len;
62 io_hdr.cmdp = inqCmdBlk;
64 io_hdr.timeout = DEF_TIMEOUT;
66 if (ioctl(sg_fd, SG_IO, &io_hdr) < 0)
69 /* treat SG_ERR here to get rid of sg_err.[ch] */
70 io_hdr.status &= 0x7e;
71 if ((0 == io_hdr.status) && (0 == io_hdr.host_status) &&
72 (0 == io_hdr.driver_status))
74 if ((SCSI_CHECK_CONDITION == io_hdr.status) ||
75 (SCSI_COMMAND_TERMINATED == io_hdr.status) ||
76 (SG_ERR_DRIVER_SENSE == (0xf & io_hdr.driver_status))) {
77 if (io_hdr.sbp && (io_hdr.sb_len_wr > 2)) {
79 unsigned char * sense_buffer = io_hdr.sbp;
80 if (sense_buffer[0] & 0x2)
81 sense_key = sense_buffer[1] & 0xf;
83 sense_key = sense_buffer[2] & 0xf;
84 if(RECOVERED_ERROR == sense_key)
94 unsigned char turCmdBlk[TUR_CMD_LEN] = { 0x00, 0, 0, 0, 0, 0 };
95 struct sg_io_hdr io_hdr;
96 unsigned char sense_buffer[32];
98 memset(&io_hdr, 0, sizeof (struct sg_io_hdr));
99 io_hdr.interface_id = 'S';
100 io_hdr.cmd_len = sizeof (turCmdBlk);
101 io_hdr.mx_sb_len = sizeof (sense_buffer);
102 io_hdr.dxfer_direction = SG_DXFER_NONE;
103 io_hdr.cmdp = turCmdBlk;
104 io_hdr.sbp = sense_buffer;
105 io_hdr.timeout = 20000;
108 if (ioctl(fd, SG_IO, &io_hdr) < 0)
111 if (io_hdr.info & SG_INFO_OK_MASK)
118 hp_sw (int fd, char *msg, void **context)
120 char buff[MX_ALLOC_LEN];
121 struct sw_checker_context * ctxt = NULL;
125 * caller passed in a context : use its address
128 ctxt = (struct sw_checker_context *) (*context);
131 * passed in context is uninitialized or volatile context :
135 ctxt = malloc(sizeof(struct sw_checker_context));
136 memset(ctxt, 0, sizeof(struct sw_checker_context));
139 MSG("cannot allocate context");
147 if ((ctxt->run_count % HEAVY_CHECK_COUNT) == 0) {
157 if (0 != do_inq(fd, 0, 1, 0x80, buff, MX_ALLOC_LEN, 0)) {
164 MSG(MSG_HP_SW_GHOST);
173 * caller told us he doesn't want to keep the context :