make prioritizers use checker_timeout, if set
[multipath-tools/.git] / libmultipath / prioritizers / emc.c
1 #include <stdio.h>
2 #include <string.h>
3 #include <sys/ioctl.h>
4
5 #include <sg_include.h>
6 #include <debug.h>
7 #include <prio.h>
8 #include <structs.h>
9
10 #define INQUIRY_CMD     0x12
11 #define INQUIRY_CMDLEN  6
12
13 #define pp_emc_log(prio, msg) condlog(prio, "%s: emc prio: " msg, dev)
14
15 int emc_clariion_prio(const char *dev, int fd)
16 {
17         unsigned char sense_buffer[128];
18         unsigned char sb[128];
19         unsigned char inqCmdBlk[INQUIRY_CMDLEN] = {INQUIRY_CMD, 1, 0xC0, 0,
20                                                 sizeof(sense_buffer), 0};
21         struct sg_io_hdr io_hdr;
22         int ret = PRIO_UNDEF;
23
24         memset(&io_hdr, 0, sizeof (struct sg_io_hdr));
25         memset(&sense_buffer, 0, 128);
26         io_hdr.interface_id = 'S';
27         io_hdr.cmd_len = sizeof (inqCmdBlk);
28         io_hdr.mx_sb_len = sizeof (sb);
29         io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
30         io_hdr.dxfer_len = sizeof (sense_buffer);
31         io_hdr.dxferp = sense_buffer;
32         io_hdr.cmdp = inqCmdBlk;
33         io_hdr.sbp = sb;
34         io_hdr.timeout = get_prio_timeout(60000);
35         io_hdr.pack_id = 0;
36         if (ioctl(fd, SG_IO, &io_hdr) < 0) {
37                 pp_emc_log(0, "sending query command failed");
38                 goto out;
39         }
40         if (io_hdr.info & SG_INFO_OK_MASK) {
41                 pp_emc_log(0, "query command indicates error");
42                 goto out;
43         }
44
45         if (/* Verify the code page - right page & revision */
46             sense_buffer[1] != 0xc0 || sense_buffer[9] != 0x00) {
47                 pp_emc_log(0, "path unit report page in unknown format");
48                 goto out;
49         }
50
51         if ( /* Effective initiator type */
52                 sense_buffer[27] != 0x03
53                 /*
54                  * Failover mode should be set to 1 (PNR failover mode)
55                  * or 4 (ALUA failover mode).
56                  */
57                 || (((sense_buffer[28] & 0x07) != 0x04) &&
58                     ((sense_buffer[28] & 0x07) != 0x06))
59                 /* Arraycommpath should be set to 1 */
60                 || (sense_buffer[30] & 0x04) != 0x04) {
61                 pp_emc_log(0, "path not correctly configured for failover");
62                 goto out;
63         }
64
65         if ( /* LUN operations should indicate normal operations */
66                 sense_buffer[48] != 0x00) {
67                 pp_emc_log(0, "path not available for normal operations");
68                 goto out;
69         }
70
71         /* LUN state: unbound, bound, or owned */
72         ret = sense_buffer[4];
73
74         /* Is the default owner equal to this path? */
75         /* Note this will switch to the default priority group, even if
76          * it is not the currently active one. */
77         if (sense_buffer[5] == sense_buffer[8])
78                 ret+=2;
79
80 out:
81         return(ret);
82 }
83
84 int getprio (struct path * pp, char * args)
85 {
86         return emc_clariion_prio(pp->dev, pp->fd);
87 }