]>
Commit | Line | Data |
---|---|---|
dc01aad8 SS |
1 | --- |
2 | libmultipath/checkers.h | 3 + | |
3 | libmultipath/checkers/Makefile | 4 + | |
d8602e2a | 4 | libmultipath/checkers/tur.c | 123 +++++++++++++++++++++++++++++++++++++++-- |
dc01aad8 | 5 | multipath.conf.annotated | 5 + |
d8602e2a | 6 | 4 files changed, 128 insertions(+), 7 deletions(-) |
dc01aad8 | 7 | |
d8602e2a | 8 | Index: multipath-tools-120613/libmultipath/checkers.h |
dc01aad8 | 9 | =================================================================== |
d8602e2a SS |
10 | --- multipath-tools-120613.orig/libmultipath/checkers.h |
11 | +++ multipath-tools-120613/libmultipath/checkers.h | |
dc01aad8 SS |
12 | @@ -60,6 +60,7 @@ enum path_check_state { |
13 | ||
14 | #define DIRECTIO "directio" | |
15 | #define TUR "tur" | |
16 | +#define HP_TUR "hp_tur" | |
17 | #define HP_SW "hp_sw" | |
18 | #define RDAC "rdac" | |
19 | #define EMC_CLARIION "emc_clariion" | |
d8602e2a | 20 | @@ -77,6 +78,7 @@ enum path_check_state { |
dc01aad8 SS |
21 | #define CHECKER_MSG_LEN 256 |
22 | #define CHECKER_DEV_LEN 256 | |
23 | #define LIB_CHECKER_NAMELEN 256 | |
24 | +#define WWID_SIZE 128 | |
25 | ||
26 | struct checker { | |
27 | struct list_head node; | |
d8602e2a | 28 | @@ -88,6 +90,7 @@ struct checker { |
dc01aad8 SS |
29 | int disable; |
30 | char name[CHECKER_NAME_LEN]; | |
31 | char message[CHECKER_MSG_LEN]; /* comm with callers */ | |
32 | + char wwid[WWID_SIZE]; /* LUN wwid */ | |
33 | void * context; /* store for persistent data */ | |
34 | void ** mpcontext; /* store for persistent data shared | |
35 | multipath-wide. Use MALLOC if | |
d8602e2a | 36 | Index: multipath-tools-120613/libmultipath/checkers/Makefile |
dc01aad8 | 37 | =================================================================== |
d8602e2a SS |
38 | --- multipath-tools-120613.orig/libmultipath/checkers/Makefile |
39 | +++ multipath-tools-120613/libmultipath/checkers/Makefile | |
dc01aad8 SS |
40 | @@ -8,6 +8,7 @@ LIBS= \ |
41 | libcheckcciss_tur.so \ | |
42 | libcheckreadsector0.so \ | |
43 | libchecktur.so \ | |
44 | + libcheckhp_tur.so \ | |
45 | libcheckdirectio.so \ | |
46 | libcheckemc_clariion.so \ | |
47 | libcheckhp_sw.so \ | |
48 | @@ -23,6 +24,9 @@ libcheckdirectio.so: libsg.o directio.o | |
49 | libcheck%.so: libsg.o %.o | |
d8602e2a | 50 | $(CC) $(LDFLAGS) $(SHARED_FLAGS) -o $@ $^ |
dc01aad8 SS |
51 | |
52 | +hp_tur.o: tur.c | |
53 | + $(CC) $(CFLAGS) -DCHECK_WWID -c -o $@ $< | |
54 | + | |
55 | install: | |
56 | $(INSTALL_PROGRAM) -m 755 $(LIBS) $(DESTDIR)$(libdir) | |
57 | ||
d8602e2a | 58 | Index: multipath-tools-120613/libmultipath/checkers/tur.c |
dc01aad8 | 59 | =================================================================== |
d8602e2a SS |
60 | --- multipath-tools-120613.orig/libmultipath/checkers/tur.c |
61 | +++ multipath-tools-120613/libmultipath/checkers/tur.c | |
62 | @@ -24,12 +24,101 @@ | |
dc01aad8 SS |
63 | #define TUR_CMD_LEN 6 |
64 | #define HEAVY_CHECK_COUNT 10 | |
65 | ||
66 | +#ifdef CHECK_WWID | |
67 | +#define MSG_TUR_UP "HP tur checker reports path is up" | |
68 | +#define MSG_TUR_DOWN "HP tur checker reports path is down" | |
69 | +#define MSG_TUR_GHOST "HP tur checker reports path is in standby state" | |
d8602e2a SS |
70 | +#define MSG_TUR_RUNNING "HP tur checker still running" |
71 | +#define MSG_TUR_TIMEOUT "HP tur checker timed out" | |
72 | +#define MSG_TUR_FAILED "HP tur checker failed to initialize" | |
dc01aad8 SS |
73 | +#define EVPD 0x01 |
74 | +#define PAGE_83 0x83 | |
75 | +#define INQUIRY_CMD 0x12 | |
76 | +#define INQUIRY_CMDLEN 6 | |
77 | +#define SCSI_INQ_BUFF_LEN 96 | |
78 | +#else | |
79 | #define MSG_TUR_UP "tur checker reports path is up" | |
80 | #define MSG_TUR_DOWN "tur checker reports path is down" | |
81 | #define MSG_TUR_GHOST "tur checker reports path is in standby state" | |
d8602e2a SS |
82 | #define MSG_TUR_RUNNING "tur checker still running" |
83 | #define MSG_TUR_TIMEOUT "tur checker timed out" | |
84 | #define MSG_TUR_FAILED "tur checker failed to initialize" | |
dc01aad8 SS |
85 | +#endif |
86 | + | |
87 | +#ifdef CHECK_WWID | |
88 | +static int | |
d8602e2a | 89 | +do_inq(int fd, unsigned int timeout, char * wwid) |
dc01aad8 SS |
90 | +{ |
91 | + int ret = -1; | |
92 | + unsigned char inq_cmd[INQUIRY_CMDLEN] = | |
93 | + {INQUIRY_CMD, EVPD, PAGE_83, 0, SCSI_INQ_BUFF_LEN, 0 }; | |
94 | + unsigned char sense_buffer[32]; | |
95 | + unsigned char resp_buffer[SCSI_INQ_BUFF_LEN]; | |
96 | + char *pbuff; | |
97 | + | |
98 | + int m,k; | |
99 | + int retry_tur = 5; | |
100 | + struct sg_io_hdr io_hdr; | |
101 | + | |
102 | +retry: | |
103 | + memset(resp_buffer, 0, sizeof(resp_buffer)); | |
104 | + memset(&io_hdr, 0, sizeof(struct sg_io_hdr)); | |
105 | + | |
106 | + io_hdr.interface_id = 'S'; | |
107 | + io_hdr.cmd_len = sizeof(inq_cmd); | |
108 | + io_hdr.mx_sb_len = sizeof(sense_buffer); | |
109 | + io_hdr.dxfer_direction = -3; // Data transfer from the device. | |
110 | + io_hdr.dxfer_len = sizeof(resp_buffer); | |
111 | + io_hdr.dxferp = (unsigned char *)resp_buffer; | |
112 | + io_hdr.cmdp = inq_cmd; | |
113 | + io_hdr.sbp = sense_buffer; | |
d8602e2a | 114 | + io_hdr.timeout = timeout; // IOCTL timeout value. |
dc01aad8 | 115 | + |
d8602e2a | 116 | + if (ioctl(fd, SG_IO, &io_hdr) < 0) { |
dc01aad8 SS |
117 | + condlog(0, "SG_IO ioctl failed: %s", strerror(errno)); |
118 | + return ret; | |
119 | + } | |
120 | + if (io_hdr.info & SG_INFO_OK_MASK){ | |
121 | + int key = 0, asc, ascq; | |
122 | + | |
123 | + if (io_hdr.host_status == DID_BUS_BUSY || | |
124 | + io_hdr.host_status == DID_ERROR || | |
125 | + io_hdr.host_status == DID_TRANSPORT_DISRUPTED) { | |
126 | + if (--retry_tur) | |
127 | + goto retry; | |
128 | + } | |
129 | + if (io_hdr.sb_len_wr > 3) { | |
130 | + if (io_hdr.sbp[0] == 0x72 || io_hdr.sbp[0] == 0x73) { | |
131 | + key = io_hdr.sbp[1] & 0x0f; | |
132 | + asc = io_hdr.sbp[2]; | |
133 | + ascq = io_hdr.sbp[3]; | |
134 | + } else if (io_hdr.sb_len_wr > 13 && | |
135 | + ((io_hdr.sbp[0] & 0x7f) == 0x70 || | |
136 | + (io_hdr.sbp[0] & 0x7f) == 0x71)) { | |
137 | + key = io_hdr.sbp[2] & 0x0f; | |
138 | + asc = io_hdr.sbp[12]; | |
139 | + ascq = io_hdr.sbp[13]; | |
140 | + } | |
141 | + } | |
142 | + if (key == 0x6) { | |
143 | + /* Unit Attention, retry */ | |
144 | + if (--retry_tur) | |
145 | + goto retry; | |
146 | + } | |
147 | + return ret; | |
148 | + } | |
149 | + | |
150 | + pbuff = (char *) resp_buffer; | |
151 | + | |
152 | + wwid[0] = '3'; | |
153 | + for (m = 8, k = 1; m < 11; ++m, k+=2) | |
154 | + sprintf(&wwid[k], "%02x", (unsigned int)pbuff[m] & 0xff); | |
155 | + for (m = 11; m < 24; ++m, k+=2) | |
156 | + sprintf(&wwid[k], "%02x", (unsigned int)pbuff[m] & 0xff); | |
157 | + | |
158 | + return (ret = 0); | |
159 | +} | |
160 | +#endif | |
161 | ||
162 | struct tur_checker_context { | |
d8602e2a SS |
163 | dev_t devt; |
164 | @@ -43,6 +132,7 @@ struct tur_checker_context { | |
165 | pthread_cond_t active; | |
166 | pthread_spinlock_t hldr_lock; | |
167 | int holders; | |
168 | + char wwid[WWID_SIZE]; | |
169 | char message[CHECKER_MSG_LEN]; | |
170 | }; | |
dc01aad8 | 171 | |
d8602e2a SS |
172 | @@ -100,12 +190,15 @@ void libcheck_free (struct checker * c) |
173 | #define TUR_MSG(msg, fmt, args...) snprintf(msg, CHECKER_MSG_LEN, fmt, ##args); | |
dc01aad8 | 174 | |
d8602e2a SS |
175 | int |
176 | -tur_check(int fd, unsigned int timeout, char *msg) | |
177 | +tur_check (int fd, unsigned int timeout, char *msg, char *wwid) | |
178 | { | |
179 | struct sg_io_hdr io_hdr; | |
dc01aad8 SS |
180 | unsigned char turCmdBlk[TUR_CMD_LEN] = { 0x00, 0, 0, 0, 0, 0 }; |
181 | unsigned char sense_buffer[32]; | |
182 | int retry_tur = 5; | |
183 | +#ifdef CHECK_WWID | |
d8602e2a | 184 | + char new_wwid[WWID_SIZE]; |
dc01aad8 SS |
185 | +#endif |
186 | ||
187 | retry: | |
188 | memset(&io_hdr, 0, sizeof (struct sg_io_hdr)); | |
d8602e2a SS |
189 | @@ -179,6 +272,24 @@ tur_check(int fd, unsigned int timeout, |
190 | TUR_MSG(msg, MSG_TUR_DOWN); | |
dc01aad8 SS |
191 | return PATH_DOWN; |
192 | } | |
193 | +#ifdef CHECK_WWID | |
d8602e2a | 194 | + if (!do_inq(fd, timeout, new_wwid)) { |
dc01aad8 | 195 | + |
d8602e2a SS |
196 | + if(!strcmp(wwid, "\0")) { |
197 | + strcpy(wwid, new_wwid); | |
dc01aad8 SS |
198 | + goto up; |
199 | + } | |
200 | + | |
d8602e2a | 201 | + if (strcmp(wwid , new_wwid)) { |
dc01aad8 SS |
202 | + condlog(0, |
203 | + "hp_tur: Lun collided. new_wwid %s old_wwid %s", | |
d8602e2a SS |
204 | + new_wwid, wwid); |
205 | + TUR_MSG(msg, MSG_TUR_DOWN); | |
dc01aad8 SS |
206 | + return PATH_DOWN; |
207 | + } | |
208 | + } | |
209 | +up: | |
210 | +#endif | |
d8602e2a | 211 | TUR_MSG(msg, MSG_TUR_UP); |
dc01aad8 SS |
212 | return PATH_UP; |
213 | } | |
d8602e2a SS |
214 | @@ -215,7 +326,7 @@ void *tur_thread(void *ctx) |
215 | ct->state = PATH_PENDING; | |
216 | pthread_mutex_unlock(&ct->lock); | |
217 | ||
218 | - state = tur_check(ct->fd, ct->timeout, ct->message); | |
219 | + state = tur_check(ct->fd, ct->timeout, ct->message, ct->wwid); | |
220 | ||
221 | /* TUR checker done */ | |
222 | pthread_mutex_lock(&ct->lock); | |
223 | @@ -275,7 +386,7 @@ libcheck_check (struct checker * c) | |
224 | ct->devt = sb.st_rdev; | |
225 | ||
226 | if (c->sync) | |
227 | - return tur_check(c->fd, c->timeout, c->message); | |
228 | + return tur_check(c->fd, c->timeout, c->message, ct->wwid); | |
229 | ||
230 | /* | |
231 | * Async mode | |
232 | @@ -319,7 +430,8 @@ libcheck_check (struct checker * c) | |
233 | pthread_mutex_unlock(&ct->lock); | |
234 | condlog(3, "%d:%d: tur thread not responding, " | |
235 | "using sync mode", TUR_DEVT(ct)); | |
236 | - return tur_check(c->fd, c->timeout, c->message); | |
237 | + return tur_check(c->fd, c->timeout, c->message, | |
238 | + ct->wwid); | |
239 | } | |
240 | /* Start new TUR checker */ | |
241 | ct->state = PATH_UNCHECKED; | |
242 | @@ -337,7 +449,8 @@ libcheck_check (struct checker * c) | |
243 | ct->holders--; | |
244 | condlog(3, "%d:%d: failed to start tur thread, using" | |
245 | " sync mode", TUR_DEVT(ct)); | |
246 | - return tur_check(c->fd, c->timeout, c->message); | |
247 | + return tur_check(c->fd, c->timeout, c->message, | |
248 | + ct->wwid); | |
249 | } | |
250 | pthread_attr_destroy(&attr); | |
251 | tur_timeout(&tsp); | |
252 | Index: multipath-tools-120613/multipath.conf.annotated | |
dc01aad8 | 253 | =================================================================== |
d8602e2a SS |
254 | --- multipath-tools-120613.orig/multipath.conf.annotated |
255 | +++ multipath-tools-120613/multipath.conf.annotated | |
256 | @@ -96,7 +96,8 @@ | |
dc01aad8 SS |
257 | # # name : path_checker, checker |
258 | # # scope : multipath & multipathd | |
259 | # # desc : the default method used to determine the paths' state | |
260 | -# # values : readsector0|tur|emc_clariion|hp_sw|directio|rdac|cciss_tur | |
261 | +# # values : readsector0|tur|emc_clariion|hp_sw|directio|rdac| | |
262 | +# cciss_tur|hp_tur | |
263 | # # default : directio | |
264 | # # | |
265 | # path_checker directio | |
d8602e2a SS |
266 | @@ -493,7 +494,7 @@ |
267 | # # scope : multipathd & multipathd | |
268 | # # desc : path checking algorithm to use to check path state | |
dc01aad8 SS |
269 | # # values : readsector0|tur|emc_clariion|hp_sw|directio|rdac| |
270 | -# # cciss_tur | |
271 | +# # cciss_tur|hp_tur | |
272 | # # | |
273 | # path_checker directio | |
274 | # |