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