[build] legacy files update
[platform/upstream/multipath-tools.git] / libcheckers / emc_clariion.c
1 /*
2  * Copyright (c) 2004, 2005 Lars Marowsky-Bree
3  */
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <sys/types.h>
8 #include <sys/stat.h>
9 #include <unistd.h>
10 #include <fcntl.h>
11 #include <sys/ioctl.h>
12 #include <errno.h>
13
14 #include "path_state.h"
15 #include "checkers.h"
16
17 #include "../libmultipath/sg_include.h"
18
19 #define INQUIRY_CMD     0x12
20 #define INQUIRY_CMDLEN  6
21 #define HEAVY_CHECK_COUNT       10
22
23 struct emc_clariion_checker_context {
24         int run_count;
25         char wwn[16];
26         unsigned wwn_set;
27 };
28
29 int emc_clariion(int fd, char *msg, void **context)
30 {
31         unsigned char sense_buffer[256] = { 0, };
32         unsigned char sb[128] = { 0, };
33         unsigned char inqCmdBlk[INQUIRY_CMDLEN] = {INQUIRY_CMD, 1, 0xC0, 0,
34                                                 sizeof(sb), 0};
35         struct sg_io_hdr io_hdr;
36         struct emc_clariion_checker_context * ctxt = NULL;
37         int ret;
38
39         /*
40          * caller passed in a context : use its address
41          */
42         if (context)
43                 ctxt = (struct emc_clariion_checker_context *) (*context);
44
45         /*
46          * passed in context is uninitialized or volatile context :
47          * initialize it
48          */
49         if (!ctxt) {
50                 ctxt = malloc(sizeof(struct emc_clariion_checker_context));
51                 memset(ctxt, 0, sizeof(struct emc_clariion_checker_context));
52
53                 if (!ctxt) {
54                         MSG("cannot allocate context");
55                         return -1;
56                 }
57                 if (context)
58                         *context = ctxt;
59         }
60         ctxt->run_count++;
61
62         if ((ctxt->run_count % HEAVY_CHECK_COUNT) == 0) {
63                 ctxt->run_count = 0;
64                 /* do stuff */
65         }
66
67         if (fd <= 0) {
68                 MSG("no usable fd");
69                 ret = -1;
70                 goto out;
71         }
72         memset(&io_hdr, 0, sizeof (struct sg_io_hdr));
73         io_hdr.interface_id = 'S';
74         io_hdr.cmd_len = sizeof (inqCmdBlk);
75         io_hdr.mx_sb_len = sizeof (sb);
76         io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
77         io_hdr.dxfer_len = sizeof (sense_buffer);
78         io_hdr.dxferp = sense_buffer;
79         io_hdr.cmdp = inqCmdBlk;
80         io_hdr.sbp = sb;
81         io_hdr.timeout = 60000;
82         io_hdr.pack_id = 0;
83         if (ioctl(fd, SG_IO, &io_hdr) < 0) {
84                 MSG("emc_clariion_checker: sending query command failed");
85                 ret = PATH_DOWN;
86                 goto out;
87         }
88         if (io_hdr.info & SG_INFO_OK_MASK) {
89                 MSG("emc_clariion_checker: query command indicates error");
90                 ret = PATH_DOWN;
91                 goto out;
92         }
93         if (/* Verify the code page - right page & revision */
94             sense_buffer[1] != 0xc0 || sense_buffer[9] != 0x00) {
95                 MSG("emc_clariion_checker: Path unit report page in unknown format");
96                 ret = PATH_DOWN;
97                 goto out;
98         }
99
100         if ( /* Effective initiator type */
101                 sense_buffer[27] != 0x03
102                 /* Failover mode should be set to 1 */        
103                 || (sense_buffer[28] & 0x07) != 0x04
104                 /* Arraycommpath should be set to 1 */
105                 || (sense_buffer[30] & 0x04) != 0x04) {
106                 MSG("emc_clariion_checker: Path not correctly configured for failover");
107                 ret = PATH_DOWN;
108                 goto out;
109         }
110
111         if ( /* LUN operations should indicate normal operations */
112                 sense_buffer[48] != 0x00) {
113                 MSG("emc_clariion_checker: Path not available for normal operations");
114                 ret = PATH_SHAKY;
115                 goto out;
116         }
117
118 #if 0
119         /* This is not actually an error as the failover to this group
120          * _would_ bind the path */
121         if ( /* LUN should at least be bound somewhere */
122                 sense_buffer[4] != 0x00) {
123                 ret = PATH_UP;
124                 goto out;
125         }
126 #endif  
127         
128         /*
129          * store the LUN WWN there and compare that it indeed did not
130          * change in between, to protect against the path suddenly
131          * pointing somewhere else.
132          */
133         if (context && ctxt->wwn_set) {
134                 if (memcmp(ctxt->wwn, &sense_buffer[10], 16) != 0) {
135                         MSG("emc_clariion_checker: Logical Unit WWN has changed!");
136                         ret = PATH_DOWN;
137                         goto out;
138                 }
139         } else {
140                 memcpy(ctxt->wwn, &sense_buffer[10], 16);
141                 ctxt->wwn_set = 1;
142         }
143         
144         
145         MSG("emc_clariion_checker: Path healthy");
146         ret = PATH_UP;
147 out:
148         /*
149          * caller told us he doesn't want to keep the context :
150          * free it
151          */
152         if (!context)
153                 free(ctxt);
154
155         return(ret);
156 }