alua: Handle LBA_DEPENDENT state
[multipath-tools/.git] / libmultipath / prioritizers / rdac.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
9 #define INQUIRY_CMD     0x12
10 #define INQUIRY_CMDLEN  6
11
12 #define pp_rdac_log(prio, msg) condlog(prio, "%s: rdac prio: " msg, dev)
13
14 int rdac_prio(const char *dev, int fd)
15 {
16         unsigned char sense_buffer[256];
17         unsigned char sb[128];
18         unsigned char inqCmdBlk[INQUIRY_CMDLEN] = {INQUIRY_CMD, 1, 0xC9, 0,
19                                                 sizeof(sb), 0};
20         struct sg_io_hdr io_hdr;
21         int ret = 0;
22
23         memset(&io_hdr, 0, sizeof (struct sg_io_hdr));
24         io_hdr.interface_id = 'S';
25         io_hdr.cmd_len = sizeof (inqCmdBlk);
26         io_hdr.mx_sb_len = sizeof (sb);
27         io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
28         io_hdr.dxfer_len = sizeof (sense_buffer);
29         io_hdr.dxferp = sense_buffer;
30         io_hdr.cmdp = inqCmdBlk;
31         io_hdr.sbp = sb;
32         io_hdr.timeout = 60000;
33         io_hdr.pack_id = 0;
34         if (ioctl(fd, SG_IO, &io_hdr) < 0) {
35                 pp_rdac_log(0, "sending inquiry command failed");
36                 goto out;
37         }
38         if (io_hdr.info & SG_INFO_OK_MASK) {
39                 pp_rdac_log(0, "inquiry command indicates error");
40                 goto out;
41         }
42
43         if (/* Verify the code page - right page & page identifier */
44             sense_buffer[1] != 0xc9 ||
45             sense_buffer[3] != 0x2c ||
46             sense_buffer[4] != 'v' ||
47             sense_buffer[5] != 'a' ||
48             sense_buffer[6] != 'c' ) {
49                 pp_rdac_log(0, "volume access control page in unknown format");
50                 goto out;
51         }
52
53         if ( /* Current Volume Path Bit */
54                 ( sense_buffer[8] & 0x01) == 0x01 ) {
55                 /*
56                  * This volume was owned by the controller receiving
57                  * the inquiry command.
58                  */
59                 ret |= 0x02;
60         }
61
62         /* Volume Preferred Path Priority */
63         switch ( sense_buffer[9] & 0x0F ) {
64         case 0x01:
65                 /*
66                  * Access to this volume is most preferred through
67                  * this path and other paths with this value.
68                  */
69                 ret |= 0x04;
70                 break;
71         case 0x02:
72                 /*
73                  * Access to this volume through this path is to be used
74                  * as a secondary path. Typically this path would be used
75                  * for fail-over situations.
76                  */
77                 ret |= 0x01;
78                 break;
79         default:
80                 /* Reserved values */
81                 break;
82         }
83
84         /* For ioship mode set the bit 3 (00001000) */
85         if ((sense_buffer[8] >> 5) & 0x01)
86                 ret |= 0x08;
87
88 out:
89         return(ret);
90 }
91
92 int getprio (struct path * pp, char * args)
93 {
94         return rdac_prio(pp->dev, pp->fd);
95 }