4f46ad9503e90ed4187baad6955719e47b6cc284
[multipath-tools/.git] / libmultipath / prioritizers / datacore.c
1 /*
2  * (C) 2010 Christophe Varoqui
3  * (C) 2009 Dembach Goo Infromatik GmbH & Co KG
4  * Manon Goo <manon.goo@dg-i.net>
5  *
6  * datacore.c
7  * Version 0.9
8  *
9  * This program was inspired by work from
10  * Matthias Rudolph <matthias.rudolph@hds.com>
11  *
12  * This work is made available on the basis of the
13  * GPLv2 for detials see <http://www.gnu.org/licenses/>.
14  *
15  * Manon Goo 2009
16  *
17  *
18  */
19
20 #include <stdio.h>
21 #include <sys/ioctl.h>
22
23 #include <sys/stat.h>
24 #include <sg_include.h>
25 #include <debug.h>
26 #include <prio.h>
27 #include <structs.h>
28
29 #define INQ_REPLY_LEN 255
30 #define INQ_CMD_CODE 0x12
31 #define INQ_CMD_LEN 6
32
33 #define dc_log(prio, msg) condlog(prio, "%s: datacore prio: " msg, dev)
34
35 int datacore_prio (const char *dev, int sg_fd, char * args)
36 {
37         int k;
38         char vendor[8];
39         char product[32];
40         char luname[32];
41         char wwpn[32];
42         char sdsname[32];
43         unsigned char inqCmdBlk[INQ_CMD_LEN] = { INQ_CMD_CODE, 0, 0, 0, INQ_REPLY_LEN, 0 };
44         unsigned char inqBuff[INQ_REPLY_LEN];
45         unsigned char *inqBuffp = inqBuff;
46         unsigned char sense_buffer[32];
47         sg_io_hdr_t io_hdr;
48
49         int timeout = 2000;
50         char preferredsds_buff[255] = "";
51         char * preferredsds = &preferredsds_buff[0];
52
53         if (!args) {
54                 dc_log(0, "need prio_args with preferredsds set");
55                 return 0;
56         }
57
58         if (sscanf(args, "timeout=%i preferredsds=%s",
59                    &timeout, preferredsds) == 2) {}
60         else if (sscanf(args, "preferredsds=%s timeout=%i",
61                         preferredsds, &timeout) == 2) {}
62         else if (sscanf(args, "preferredsds=%s",
63                         preferredsds) == 1) {}
64         else {
65                 dc_log(0, "unexpected prio_args format");
66                 return 0;
67         }
68
69         // on error just return prio 0
70         if (strlen(preferredsds) <= 1) {
71                 dc_log(0, "prio args: preferredsds too short (1 character min)");
72                 return 0;
73         }
74         if ((timeout < 500) || (timeout > 20000)) {
75                 dc_log(0, "prio args: timeout out of bounds [500:20000]");
76                 return 0;
77         }
78         if ((ioctl(sg_fd, SG_GET_VERSION_NUM, &k) < 0) || (k < 30000))
79                 return 0;
80
81         memset (&io_hdr, 0, sizeof (sg_io_hdr_t));
82         io_hdr.interface_id = 'S';
83         io_hdr.cmd_len = sizeof (inqCmdBlk);
84         io_hdr.mx_sb_len = sizeof (sense_buffer);
85         io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
86         io_hdr.dxfer_len = INQ_REPLY_LEN;
87         io_hdr.dxferp = inqBuff;
88         io_hdr.cmdp = inqCmdBlk;
89         io_hdr.sbp = sense_buffer;
90         io_hdr.timeout = timeout;
91
92         // on error just return prio 0
93         if (ioctl(sg_fd, SG_IO, &io_hdr) < 0)
94                 return 0;
95         if ((io_hdr.info & SG_INFO_OK_MASK) != SG_INFO_OK)
96                 return 0;
97
98         snprintf(vendor, 8, "%.8s\n", inqBuffp + 8);
99         snprintf(product, 17, "%.16s", inqBuffp + 16);
100         snprintf(luname, 21, "%.19s", inqBuffp + 36);
101         snprintf(wwpn, 17, "%.16s", inqBuffp + 96);
102         snprintf(sdsname, 17, "%.16s", inqBuffp + 112);
103
104         if (strstr(sdsname , preferredsds))
105                 return 1;
106         return 0;
107 }
108
109 int getprio (struct path * pp, char * args)
110 {
111         return datacore_prio(pp->dev, pp->fd, args);
112 }