[build] legacy files update
[platform/upstream/multipath-tools.git] / libcheckers / readsector0.c
1 /*
2  * Copyright (c) 2004, 2005 Christophe Varoqui
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 SENSE_BUFF_LEN 32
20 #define DEF_TIMEOUT 60000
21
22 #define MSG_READSECTOR0_UP      "readsector0 checker reports path is up"
23 #define MSG_READSECTOR0_DOWN    "readsector0 checker reports path is down"
24
25 struct readsector0_checker_context {
26         void * dummy;
27 };
28
29 static int
30 sg_read (int sg_fd, unsigned char * buff)
31 {
32         /* defaults */
33         int blocks = 1;
34         long long start_block = 0;
35         int bs = 512;
36         int cdbsz = 10;
37         int * diop = NULL;
38
39         unsigned char rdCmd[cdbsz];
40         unsigned char senseBuff[SENSE_BUFF_LEN];
41         struct sg_io_hdr io_hdr;
42         int res;
43         int rd_opcode[] = {0x8, 0x28, 0xa8, 0x88};
44         int sz_ind;
45         
46         memset(rdCmd, 0, cdbsz);
47         sz_ind = 1;
48         rdCmd[0] = rd_opcode[sz_ind];
49         rdCmd[2] = (unsigned char)((start_block >> 24) & 0xff);
50         rdCmd[3] = (unsigned char)((start_block >> 16) & 0xff);
51         rdCmd[4] = (unsigned char)((start_block >> 8) & 0xff);
52         rdCmd[5] = (unsigned char)(start_block & 0xff);
53         rdCmd[7] = (unsigned char)((blocks >> 8) & 0xff);
54         rdCmd[8] = (unsigned char)(blocks & 0xff);
55
56         memset(&io_hdr, 0, sizeof(struct sg_io_hdr));
57         io_hdr.interface_id = 'S';
58         io_hdr.cmd_len = cdbsz;
59         io_hdr.cmdp = rdCmd;
60         io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
61         io_hdr.dxfer_len = bs * blocks;
62         io_hdr.dxferp = buff;
63         io_hdr.mx_sb_len = SENSE_BUFF_LEN;
64         io_hdr.sbp = senseBuff;
65         io_hdr.timeout = DEF_TIMEOUT;
66         io_hdr.pack_id = (int)start_block;
67         if (diop && *diop)
68         io_hdr.flags |= SG_FLAG_DIRECT_IO;
69
70         while (((res = ioctl(sg_fd, SG_IO, &io_hdr)) < 0) && (EINTR == errno));
71
72         if (res < 0) {
73                 if (ENOMEM == errno) {
74                         return PATH_UP;
75                 }
76                 return PATH_DOWN;
77         }
78
79         if ((0 == io_hdr.status) &&
80             (0 == io_hdr.host_status) &&
81             (0 == io_hdr.driver_status)) {
82                 return PATH_UP;
83         } else {
84                 return PATH_DOWN;
85         }
86 }
87
88 extern int
89 readsector0 (int fd, char *msg, void **context)
90 {
91         unsigned char buf[512];
92         struct readsector0_checker_context * ctxt = NULL;
93         int ret;
94
95         /*
96          * caller passed in a context : use its address
97          */
98         if (context)
99                 ctxt = (struct readsector0_checker_context *) (*context);
100
101         /*
102          * passed in context is uninitialized or volatile context :
103          * initialize it
104          */
105         if (!ctxt) {
106                 ctxt = malloc(sizeof(struct readsector0_checker_context));
107                 memset(ctxt, 0, sizeof(struct readsector0_checker_context));
108
109                 if (!ctxt) {
110                         MSG("cannot allocate context");
111                         return -1;
112                 }
113                 if (context)
114                         *context = ctxt;
115         }
116         if (fd <= 0) {
117                 MSG("no usable fd");
118                 ret = -1;
119                 goto out;
120         }
121         ret = sg_read(fd, &buf[0]);
122
123         switch (ret)
124         {
125         case PATH_DOWN:
126                 MSG(MSG_READSECTOR0_DOWN);
127                 break;
128         case PATH_UP:
129                 MSG(MSG_READSECTOR0_UP);
130                 break;
131         default:
132                 break;
133         }
134 out:
135         /*
136          * caller told us he doesn't want to keep the context :
137          * free it
138          */
139         if (!context)
140                 free(ctxt);
141
142         return ret;
143 }