1cab201585a58bb03ed740e6cd29d0874c81101f
[multipath-tools/.git] / libmultipath / checkers / cciss_tur.c
1 /*
2  *****************************************************************************
3  *                                                                           *
4  *     (C)  Copyright 2007 Hewlett-Packard Development Company, L.P          *
5  *                                                                           *
6  * This program is free software; you can redistribute it and/or modify it   *
7  * under the terms of the GNU General Public License as published by the Free*
8  * Software  Foundation; either version 2 of the License, or (at your option)*
9  * any later version.                                                        *
10  *                                                                           *
11  * This program is distributed in the hope that it will be useful, but       *
12  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY*
13  * or FITNESS FOR  A PARTICULAR PURPOSE. See the GNU General Public License  *
14  * for more details.                                                         *
15  *                                                                           *
16  * You should have received a copy of the GNU General Public License along   *
17  * with this program.  If not, see <http://www.gnu.org/licenses/>.           *
18  *                                                                           *
19  *****************************************************************************
20 */
21
22 /*
23  *  This program originally derived from and inspired by
24  *  Christophe Varoqui's tur.c, part of libchecker.
25  */
26
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 #include <unistd.h>
34 #include <fcntl.h>
35 #include <sys/ioctl.h>
36 #include <errno.h>
37
38 #include "checkers.h"
39
40 #include "cciss.h"
41
42 #define TUR_CMD_LEN 6
43 #define HEAVY_CHECK_COUNT       10
44
45 #define MSG_CCISS_TUR_UP        "cciss_tur checker reports path is up"
46 #define MSG_CCISS_TUR_DOWN      "cciss_tur checker reports path is down"
47
48 struct cciss_tur_checker_context {
49         void * dummy;
50 };
51
52 int libcheck_init (struct checker * c)
53 {
54         return 0;
55 }
56
57 void libcheck_free (struct checker * c)
58 {
59         return;
60 }
61
62 int libcheck_check(struct checker * c)
63 {
64         int rc;
65         int ret;
66         unsigned int lun = 0;
67         struct cciss_tur_checker_context * ctxt = NULL;
68         LogvolInfo_struct    lvi;       // logical "volume" info
69         IOCTL_Command_struct cic;       // cciss ioctl command
70
71         if ((c->fd) < 0) {
72                 MSG(c,"no usable fd");
73                 ret = -1;
74                 goto out;
75         }
76
77         rc = ioctl(c->fd, CCISS_GETLUNINFO, &lvi);
78         if ( rc != 0) {
79                 perror("Error: ");
80                 fprintf(stderr, "cciss TUR  failed in CCISS_GETLUNINFO: %s\n",
81                         strerror(errno));
82                 MSG(c,MSG_CCISS_TUR_DOWN);
83                 ret = PATH_DOWN;
84                 goto out;
85         } else {
86                 lun = lvi.LunID;
87         }
88
89         memset(&cic, 0, sizeof(cic));
90         cic.LUN_info.LogDev.VolId = lun & 0x3FFFFFFF;
91         cic.LUN_info.LogDev.Mode = 0x01; /* logical volume addressing */
92         cic.Request.CDBLen = 6;  /* need to try just 2 bytes here */
93         cic.Request.Type.Type =  TYPE_CMD; // It is a command.
94         cic.Request.Type.Attribute = ATTR_SIMPLE;
95         cic.Request.Type.Direction = XFER_NONE;
96         cic.Request.Timeout = 0;
97
98         cic.Request.CDB[0] = 0;
99         cic.Request.CDB[1] = 0;
100         cic.Request.CDB[2] = 0;
101         cic.Request.CDB[3] = 0;
102         cic.Request.CDB[4] = 0;
103         cic.Request.CDB[5] = 0;
104
105         rc = ioctl(c->fd, CCISS_PASSTHRU, &cic);
106         if (rc < 0) {
107                 fprintf(stderr, "cciss TUR  failed: %s\n",
108                         strerror(errno));
109                 MSG(c,MSG_CCISS_TUR_DOWN);
110                 ret = PATH_DOWN;
111                 goto out;
112         }
113
114         if ((cic.error_info.CommandStatus | cic.error_info.ScsiStatus )) {
115                 MSG(c,MSG_CCISS_TUR_DOWN);
116                 ret = PATH_DOWN;
117                 goto out;
118         }
119
120         MSG(c,MSG_CCISS_TUR_UP);
121
122         ret = PATH_UP;
123 out:
124         /*
125          * caller told us he doesn't want to keep the context :
126          * free it
127          */
128         if (!c->context)
129                 free(ctxt);
130
131         return(ret);
132 }