bioctl.c revision 1.5 1 1.5 xtraeme /* $NetBSD: bioctl.c,v 1.5 2007/12/05 16:29:48 xtraeme Exp $ */
2 1.1 bouyer /* $OpenBSD: bioctl.c,v 1.52 2007/03/20 15:26:06 jmc Exp $ */
3 1.1 bouyer
4 1.1 bouyer /*
5 1.1 bouyer * Copyright (c) 2004, 2005 Marco Peereboom
6 1.1 bouyer * All rights reserved.
7 1.1 bouyer *
8 1.1 bouyer * Redistribution and use in source and binary forms, with or without
9 1.1 bouyer * modification, are permitted provided that the following conditions
10 1.1 bouyer * are met:
11 1.1 bouyer * 1. Redistributions of source code must retain the above copyright
12 1.1 bouyer * notice, this list of conditions and the following disclaimer.
13 1.1 bouyer * 2. Redistributions in binary form must reproduce the above copyright
14 1.1 bouyer * notice, this list of conditions and the following disclaimer in the
15 1.1 bouyer * documentation and/or other materials provided with the distribution.
16 1.1 bouyer *
17 1.1 bouyer * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
18 1.1 bouyer * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 1.1 bouyer * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 1.1 bouyer * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
21 1.1 bouyer * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 1.1 bouyer * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 1.1 bouyer * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 1.1 bouyer * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 1.1 bouyer * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 1.1 bouyer * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 1.1 bouyer * SUCH DAMAGE.
28 1.1 bouyer *
29 1.1 bouyer */
30 1.1 bouyer #include <sys/cdefs.h>
31 1.1 bouyer
32 1.1 bouyer #ifndef lint
33 1.5 xtraeme __RCSID("$NetBSD: bioctl.c,v 1.5 2007/12/05 16:29:48 xtraeme Exp $");
34 1.1 bouyer #endif
35 1.1 bouyer
36 1.1 bouyer #include <sys/ioctl.h>
37 1.1 bouyer #include <sys/param.h>
38 1.1 bouyer #include <sys/queue.h>
39 1.1 bouyer #include <dev/biovar.h>
40 1.1 bouyer
41 1.1 bouyer #include <errno.h>
42 1.1 bouyer #include <err.h>
43 1.1 bouyer #include <fcntl.h>
44 1.1 bouyer #include <util.h>
45 1.1 bouyer #include <stdio.h>
46 1.1 bouyer #include <stdlib.h>
47 1.1 bouyer #include <string.h>
48 1.1 bouyer #include <unistd.h>
49 1.1 bouyer #include <ctype.h>
50 1.1 bouyer #include <util.h>
51 1.1 bouyer #include "strtonum.h"
52 1.1 bouyer
53 1.1 bouyer struct locator {
54 1.1 bouyer int channel;
55 1.1 bouyer int target;
56 1.1 bouyer int lun;
57 1.1 bouyer };
58 1.1 bouyer
59 1.2 xtraeme static void usage(void);
60 1.2 xtraeme static const char *str2locator(const char *, struct locator *);
61 1.1 bouyer
62 1.2 xtraeme static void bio_inq(int, char *);
63 1.2 xtraeme static void bio_alarm(int, char *);
64 1.2 xtraeme static void bio_setstate(int, char *);
65 1.2 xtraeme static void bio_setblink(int, char *, char *, int);
66 1.2 xtraeme static void bio_blink(int, char *, int, int);
67 1.2 xtraeme
68 1.2 xtraeme static int human;
69 1.2 xtraeme static int verbose;
70 1.2 xtraeme
71 1.2 xtraeme static struct bio_locate bl;
72 1.1 bouyer
73 1.1 bouyer int
74 1.1 bouyer main(int argc, char *argv[])
75 1.1 bouyer {
76 1.2 xtraeme uint64_t func = 0;
77 1.2 xtraeme char *bioc_dev, *al_arg, *bl_arg;
78 1.2 xtraeme int fd, ch, rv, blink;
79 1.2 xtraeme
80 1.2 xtraeme bioc_dev = al_arg = bl_arg = NULL;
81 1.2 xtraeme fd = ch = rv = blink = 0;
82 1.1 bouyer
83 1.1 bouyer if (argc < 2)
84 1.1 bouyer usage();
85 1.1 bouyer
86 1.2 xtraeme setprogname(*argv);
87 1.2 xtraeme
88 1.2 xtraeme while ((ch = getopt(argc, argv, "b:c:l:u:H:ha:Dv")) != -1) {
89 1.1 bouyer switch (ch) {
90 1.1 bouyer case 'a': /* alarm */
91 1.1 bouyer func |= BIOC_ALARM;
92 1.1 bouyer al_arg = optarg;
93 1.1 bouyer break;
94 1.1 bouyer case 'b': /* blink */
95 1.1 bouyer func |= BIOC_BLINK;
96 1.1 bouyer blink = BIOC_SBBLINK;
97 1.1 bouyer bl_arg = optarg;
98 1.1 bouyer break;
99 1.1 bouyer case 'u': /* unblink */
100 1.1 bouyer func |= BIOC_BLINK;
101 1.1 bouyer blink = BIOC_SBUNBLINK;
102 1.1 bouyer bl_arg = optarg;
103 1.1 bouyer break;
104 1.1 bouyer case 'H': /* set hotspare */
105 1.1 bouyer func |= BIOC_SETSTATE;
106 1.1 bouyer al_arg = optarg;
107 1.1 bouyer break;
108 1.1 bouyer case 'h':
109 1.1 bouyer human = 1;
110 1.1 bouyer break;
111 1.1 bouyer case 'i': /* inquiry */
112 1.1 bouyer func |= BIOC_INQ;
113 1.1 bouyer break;
114 1.1 bouyer case 'v':
115 1.1 bouyer verbose = 1;
116 1.1 bouyer break;
117 1.1 bouyer default:
118 1.1 bouyer usage();
119 1.1 bouyer /* NOTREACHED */
120 1.1 bouyer }
121 1.1 bouyer }
122 1.1 bouyer argc -= optind;
123 1.1 bouyer argv += optind;
124 1.1 bouyer
125 1.1 bouyer if (argc != 1)
126 1.1 bouyer usage();
127 1.1 bouyer
128 1.1 bouyer if (func == 0)
129 1.1 bouyer func |= BIOC_INQ;
130 1.2 xtraeme
131 1.2 xtraeme bioc_dev = argv[0];
132 1.1 bouyer
133 1.1 bouyer if (bioc_dev) {
134 1.2 xtraeme fd = open("/dev/bio", O_RDWR);
135 1.2 xtraeme if (fd == -1)
136 1.2 xtraeme err(EXIT_FAILURE, "Can't open %s", "/dev/bio");
137 1.1 bouyer
138 1.1 bouyer bl.bl_name = bioc_dev;
139 1.2 xtraeme rv = ioctl(fd, BIOCLOCATE, &bl);
140 1.1 bouyer if (rv == -1)
141 1.2 xtraeme errx(EXIT_FAILURE, "Can't locate %s device via %s",
142 1.1 bouyer bl.bl_name, "/dev/bio");
143 1.1 bouyer }
144 1.1 bouyer
145 1.1 bouyer if (func & BIOC_INQ) {
146 1.2 xtraeme bio_inq(fd, bioc_dev);
147 1.1 bouyer } else if (func == BIOC_ALARM) {
148 1.2 xtraeme bio_alarm(fd, al_arg);
149 1.1 bouyer } else if (func == BIOC_BLINK) {
150 1.2 xtraeme bio_setblink(fd, bioc_dev, bl_arg, blink);
151 1.1 bouyer } else if (func == BIOC_SETSTATE) {
152 1.2 xtraeme bio_setstate(fd, al_arg);
153 1.1 bouyer }
154 1.1 bouyer
155 1.2 xtraeme exit(EXIT_SUCCESS);
156 1.1 bouyer }
157 1.1 bouyer
158 1.2 xtraeme static void
159 1.1 bouyer usage(void)
160 1.1 bouyer {
161 1.2 xtraeme (void)fprintf(stderr,
162 1.4 xtraeme "usage: %s [-hv] [-a alarm-function] "
163 1.1 bouyer "[-b channel:target[.lun]]\n"
164 1.2 xtraeme "\t[-H channel:target[.lun]]\n"
165 1.2 xtraeme "\t[-u channel:target[.lun]] device\n", getprogname());
166 1.2 xtraeme exit(EXIT_FAILURE);
167 1.2 xtraeme /* NOTREACHED */
168 1.1 bouyer }
169 1.1 bouyer
170 1.2 xtraeme static const char *
171 1.1 bouyer str2locator(const char *string, struct locator *location)
172 1.1 bouyer {
173 1.1 bouyer const char *errstr;
174 1.1 bouyer char parse[80], *targ, *lun;
175 1.1 bouyer
176 1.1 bouyer strlcpy(parse, string, sizeof parse);
177 1.1 bouyer targ = strchr(parse, ':');
178 1.1 bouyer if (targ == NULL)
179 1.1 bouyer return ("target not specified");
180 1.1 bouyer *targ++ = '\0';
181 1.1 bouyer
182 1.1 bouyer lun = strchr(targ, '.');
183 1.1 bouyer if (lun != NULL) {
184 1.1 bouyer *lun++ = '\0';
185 1.1 bouyer location->lun = strtonum(lun, 0, 256, &errstr);
186 1.1 bouyer if (errstr)
187 1.2 xtraeme return errstr;
188 1.1 bouyer } else
189 1.1 bouyer location->lun = 0;
190 1.1 bouyer
191 1.1 bouyer location->target = strtonum(targ, 0, 256, &errstr);
192 1.1 bouyer if (errstr)
193 1.2 xtraeme return errstr;
194 1.1 bouyer location->channel = strtonum(parse, 0, 256, &errstr);
195 1.1 bouyer if (errstr)
196 1.2 xtraeme return errstr;
197 1.2 xtraeme return NULL;
198 1.1 bouyer }
199 1.1 bouyer
200 1.2 xtraeme static void
201 1.2 xtraeme bio_inq(int fd, char *name)
202 1.1 bouyer {
203 1.1 bouyer const char *status;
204 1.1 bouyer char size[64], scsiname[16], volname[32];
205 1.1 bouyer char percent[10], seconds[20];
206 1.1 bouyer int rv, i, d, volheader, hotspare, unused;
207 1.1 bouyer char encname[16], serial[32];
208 1.1 bouyer struct bioc_disk bd;
209 1.1 bouyer struct bioc_inq bi;
210 1.1 bouyer struct bioc_vol bv;
211 1.1 bouyer
212 1.1 bouyer memset(&bi, 0, sizeof(bi));
213 1.1 bouyer
214 1.1 bouyer bi.bi_cookie = bl.bl_cookie;
215 1.1 bouyer
216 1.2 xtraeme rv = ioctl(fd, BIOCINQ, &bi);
217 1.4 xtraeme if (rv)
218 1.4 xtraeme errx(EXIT_FAILURE, "BIOCINQ %s", strerror(errno));
219 1.1 bouyer
220 1.1 bouyer volheader = 0;
221 1.1 bouyer for (i = 0; i < bi.bi_novol; i++) {
222 1.1 bouyer memset(&bv, 0, sizeof(bv));
223 1.1 bouyer bv.bv_cookie = bl.bl_cookie;
224 1.1 bouyer bv.bv_volid = i;
225 1.1 bouyer bv.bv_percent = -1;
226 1.1 bouyer bv.bv_seconds = 0;
227 1.1 bouyer
228 1.2 xtraeme rv = ioctl(fd, BIOCVOL, &bv);
229 1.4 xtraeme if (rv)
230 1.4 xtraeme errx(EXIT_FAILURE, "BIOCVOL %s", strerror(errno));
231 1.1 bouyer
232 1.1 bouyer if (!volheader) {
233 1.1 bouyer volheader = 1;
234 1.5 xtraeme if (human)
235 1.5 xtraeme printf("%10s %-10s %4s %-8s\n",
236 1.5 xtraeme "Volume", "Status", "Size", "Device");
237 1.5 xtraeme else
238 1.5 xtraeme printf("%10s %-10s %14s %-8s\n",
239 1.5 xtraeme "Volume", "Status", "Size", "Device");
240 1.1 bouyer }
241 1.1 bouyer
242 1.1 bouyer percent[0] = '\0';
243 1.1 bouyer seconds[0] = '\0';
244 1.1 bouyer if (bv.bv_percent != -1)
245 1.1 bouyer snprintf(percent, sizeof percent,
246 1.1 bouyer " %d%% done", bv.bv_percent);
247 1.1 bouyer if (bv.bv_seconds)
248 1.1 bouyer snprintf(seconds, sizeof seconds,
249 1.1 bouyer " %u seconds", bv.bv_seconds);
250 1.1 bouyer switch (bv.bv_status) {
251 1.1 bouyer case BIOC_SVONLINE:
252 1.1 bouyer status = BIOC_SVONLINE_S;
253 1.1 bouyer break;
254 1.1 bouyer case BIOC_SVOFFLINE:
255 1.1 bouyer status = BIOC_SVOFFLINE_S;
256 1.1 bouyer break;
257 1.1 bouyer case BIOC_SVDEGRADED:
258 1.1 bouyer status = BIOC_SVDEGRADED_S;
259 1.1 bouyer break;
260 1.1 bouyer case BIOC_SVBUILDING:
261 1.1 bouyer status = BIOC_SVBUILDING_S;
262 1.1 bouyer break;
263 1.1 bouyer case BIOC_SVREBUILD:
264 1.1 bouyer status = BIOC_SVREBUILD_S;
265 1.1 bouyer break;
266 1.1 bouyer case BIOC_SVSCRUB:
267 1.1 bouyer status = BIOC_SVSCRUB_S;
268 1.1 bouyer break;
269 1.1 bouyer case BIOC_SVINVALID:
270 1.1 bouyer default:
271 1.1 bouyer status = BIOC_SVINVALID_S;
272 1.1 bouyer }
273 1.1 bouyer
274 1.1 bouyer snprintf(volname, sizeof volname, "%s %u",
275 1.1 bouyer bi.bi_dev, bv.bv_volid);
276 1.1 bouyer
277 1.1 bouyer if (bv.bv_level == -1 && bv.bv_nodisk == 1) {
278 1.1 bouyer hotspare = 1;
279 1.1 bouyer unused = 0;
280 1.1 bouyer } else if (bv.bv_level == -2 && bv.bv_nodisk == 1) {
281 1.1 bouyer unused = 1;
282 1.1 bouyer hotspare = 0;
283 1.1 bouyer } else {
284 1.1 bouyer unused = 0;
285 1.1 bouyer hotspare = 0;
286 1.1 bouyer
287 1.5 xtraeme if (human) {
288 1.1 bouyer humanize_number(size, 5,
289 1.1 bouyer (int64_t)bv.bv_size, "", HN_AUTOSCALE,
290 1.1 bouyer HN_B | HN_NOSPACE | HN_DECIMAL);
291 1.5 xtraeme printf("%10s %-10s %4s %-7s RAID %u%s%s\n",
292 1.5 xtraeme volname, status, size, bv.bv_dev,
293 1.5 xtraeme bv.bv_level, percent, seconds);
294 1.5 xtraeme } else {
295 1.1 bouyer snprintf(size, sizeof size, "%14llu",
296 1.1 bouyer (long long unsigned int)bv.bv_size);
297 1.5 xtraeme printf("%10s %-10s %14s %-7s RAID %u%s%s\n",
298 1.5 xtraeme volname, status, size, bv.bv_dev,
299 1.5 xtraeme bv.bv_level, percent, seconds);
300 1.5 xtraeme }
301 1.1 bouyer }
302 1.1 bouyer
303 1.1 bouyer for (d = 0; d < bv.bv_nodisk; d++) {
304 1.1 bouyer memset(&bd, 0, sizeof(bd));
305 1.1 bouyer bd.bd_cookie = bl.bl_cookie;
306 1.1 bouyer bd.bd_diskid = d;
307 1.1 bouyer bd.bd_volid = i;
308 1.1 bouyer
309 1.2 xtraeme rv = ioctl(fd, BIOCDISK, &bd);
310 1.4 xtraeme if (rv)
311 1.4 xtraeme errx(EXIT_FAILURE, "BIOCDISK %s",
312 1.4 xtraeme strerror(errno));
313 1.1 bouyer
314 1.1 bouyer switch (bd.bd_status) {
315 1.1 bouyer case BIOC_SDONLINE:
316 1.1 bouyer status = BIOC_SDONLINE_S;
317 1.1 bouyer break;
318 1.1 bouyer case BIOC_SDOFFLINE:
319 1.1 bouyer status = BIOC_SDOFFLINE_S;
320 1.1 bouyer break;
321 1.1 bouyer case BIOC_SDFAILED:
322 1.1 bouyer status = BIOC_SDFAILED_S;
323 1.1 bouyer break;
324 1.1 bouyer case BIOC_SDREBUILD:
325 1.1 bouyer status = BIOC_SDREBUILD_S;
326 1.1 bouyer break;
327 1.1 bouyer case BIOC_SDHOTSPARE:
328 1.1 bouyer status = BIOC_SDHOTSPARE_S;
329 1.1 bouyer break;
330 1.1 bouyer case BIOC_SDUNUSED:
331 1.1 bouyer status = BIOC_SDUNUSED_S;
332 1.1 bouyer break;
333 1.1 bouyer case BIOC_SDSCRUB:
334 1.1 bouyer status = BIOC_SDSCRUB_S;
335 1.1 bouyer break;
336 1.1 bouyer case BIOC_SDINVALID:
337 1.1 bouyer default:
338 1.1 bouyer status = BIOC_SDINVALID_S;
339 1.1 bouyer }
340 1.1 bouyer
341 1.1 bouyer if (hotspare || unused)
342 1.1 bouyer ; /* use volname from parent volume */
343 1.1 bouyer else
344 1.1 bouyer snprintf(volname, sizeof volname, " %3u",
345 1.1 bouyer bd.bd_diskid);
346 1.1 bouyer
347 1.1 bouyer if (human)
348 1.1 bouyer humanize_number(size, 5,
349 1.1 bouyer bd.bd_size, "", HN_AUTOSCALE,
350 1.1 bouyer HN_B | HN_NOSPACE | HN_DECIMAL);
351 1.1 bouyer else
352 1.1 bouyer snprintf(size, sizeof size, "%14llu",
353 1.1 bouyer (long long unsigned int)bd.bd_size);
354 1.1 bouyer snprintf(scsiname, sizeof scsiname,
355 1.1 bouyer "%u:%u.%u",
356 1.1 bouyer bd.bd_channel, bd.bd_target, bd.bd_lun);
357 1.1 bouyer if (bd.bd_procdev[0])
358 1.1 bouyer strlcpy(encname, bd.bd_procdev, sizeof encname);
359 1.1 bouyer else
360 1.1 bouyer strlcpy(encname, "noencl", sizeof encname);
361 1.1 bouyer if (bd.bd_serial[0])
362 1.1 bouyer strlcpy(serial, bd.bd_serial, sizeof serial);
363 1.1 bouyer else
364 1.1 bouyer strlcpy(serial, "unknown serial", sizeof serial);
365 1.1 bouyer
366 1.5 xtraeme if (human)
367 1.5 xtraeme printf("%10s %-10s %4s %-7s %-6s <%s>\n",
368 1.5 xtraeme volname, status, size, scsiname, encname,
369 1.5 xtraeme bd.bd_vendor);
370 1.5 xtraeme else
371 1.5 xtraeme printf("%10s %-10s %14s %-7s %-6s <%s>\n",
372 1.5 xtraeme volname, status, size, scsiname, encname,
373 1.5 xtraeme bd.bd_vendor);
374 1.1 bouyer if (verbose)
375 1.1 bouyer printf("%7s %-10s %14s %-7s %-6s '%s'\n",
376 1.1 bouyer "", "", "", "", "", serial);
377 1.1 bouyer }
378 1.1 bouyer }
379 1.1 bouyer }
380 1.1 bouyer
381 1.2 xtraeme static void
382 1.2 xtraeme bio_alarm(int fd, char *arg)
383 1.1 bouyer {
384 1.1 bouyer int rv;
385 1.1 bouyer struct bioc_alarm ba;
386 1.1 bouyer
387 1.1 bouyer ba.ba_cookie = bl.bl_cookie;
388 1.1 bouyer
389 1.1 bouyer switch (arg[0]) {
390 1.1 bouyer case 'q': /* silence alarm */
391 1.1 bouyer /* FALLTHROUGH */
392 1.1 bouyer case 's':
393 1.1 bouyer ba.ba_opcode = BIOC_SASILENCE;
394 1.1 bouyer break;
395 1.1 bouyer
396 1.1 bouyer case 'e': /* enable alarm */
397 1.1 bouyer ba.ba_opcode = BIOC_SAENABLE;
398 1.1 bouyer break;
399 1.1 bouyer
400 1.1 bouyer case 'd': /* disable alarm */
401 1.1 bouyer ba.ba_opcode = BIOC_SADISABLE;
402 1.1 bouyer break;
403 1.1 bouyer
404 1.1 bouyer case 't': /* test alarm */
405 1.1 bouyer ba.ba_opcode = BIOC_SATEST;
406 1.1 bouyer break;
407 1.1 bouyer
408 1.1 bouyer case 'g': /* get alarm state */
409 1.1 bouyer ba.ba_opcode = BIOC_GASTATUS;
410 1.1 bouyer break;
411 1.1 bouyer
412 1.1 bouyer default:
413 1.1 bouyer warnx("invalid alarm function: %s", arg);
414 1.1 bouyer return;
415 1.1 bouyer }
416 1.1 bouyer
417 1.2 xtraeme rv = ioctl(fd, BIOCALARM, &ba);
418 1.4 xtraeme if (rv)
419 1.4 xtraeme errx(EXIT_FAILURE, "BIOCALARM %s", strerror(errno));
420 1.1 bouyer
421 1.1 bouyer if (arg[0] == 'g') {
422 1.1 bouyer printf("alarm is currently %s\n",
423 1.1 bouyer ba.ba_status ? "enabled" : "disabled");
424 1.1 bouyer
425 1.1 bouyer }
426 1.1 bouyer }
427 1.1 bouyer
428 1.2 xtraeme static void
429 1.2 xtraeme bio_setstate(int fd, char *arg)
430 1.1 bouyer {
431 1.1 bouyer struct bioc_setstate bs;
432 1.1 bouyer struct locator location;
433 1.1 bouyer const char *errstr;
434 1.1 bouyer int rv;
435 1.1 bouyer
436 1.1 bouyer errstr = str2locator(arg, &location);
437 1.1 bouyer if (errstr)
438 1.1 bouyer errx(1, "Target %s: %s", arg, errstr);
439 1.1 bouyer
440 1.1 bouyer bs.bs_cookie = bl.bl_cookie;
441 1.1 bouyer bs.bs_status = BIOC_SSHOTSPARE;
442 1.1 bouyer bs.bs_channel = location.channel;
443 1.1 bouyer bs.bs_target = location.target;
444 1.1 bouyer bs.bs_lun = location.lun;
445 1.1 bouyer
446 1.2 xtraeme rv = ioctl(fd, BIOCSETSTATE, &bs);
447 1.4 xtraeme if (rv)
448 1.4 xtraeme errx(EXIT_FAILURE, "BIOCSETSTATE %s", strerror(errno));
449 1.1 bouyer }
450 1.1 bouyer
451 1.2 xtraeme static void
452 1.2 xtraeme bio_setblink(int fd, char *name, char *arg, int blink)
453 1.1 bouyer {
454 1.1 bouyer struct locator location;
455 1.1 bouyer struct bioc_inq bi;
456 1.1 bouyer struct bioc_vol bv;
457 1.1 bouyer struct bioc_disk bd;
458 1.1 bouyer struct bioc_blink bb;
459 1.1 bouyer const char *errstr;
460 1.1 bouyer int v, d, rv;
461 1.1 bouyer
462 1.1 bouyer errstr = str2locator(arg, &location);
463 1.1 bouyer if (errstr)
464 1.4 xtraeme errx(EXIT_FAILURE, "Target %s: %s", arg, errstr);
465 1.1 bouyer
466 1.1 bouyer /* try setting blink on the device directly */
467 1.1 bouyer memset(&bb, 0, sizeof(bb));
468 1.1 bouyer bb.bb_cookie = bl.bl_cookie;
469 1.1 bouyer bb.bb_status = blink;
470 1.1 bouyer bb.bb_target = location.target;
471 1.1 bouyer bb.bb_channel = location.channel;
472 1.2 xtraeme rv = ioctl(fd, BIOCBLINK, &bb);
473 1.1 bouyer if (rv == 0)
474 1.1 bouyer return;
475 1.1 bouyer
476 1.1 bouyer /* if the blink didnt work, try to find something that will */
477 1.1 bouyer
478 1.1 bouyer memset(&bi, 0, sizeof(bi));
479 1.1 bouyer bi.bi_cookie = bl.bl_cookie;
480 1.2 xtraeme rv = ioctl(fd, BIOCINQ, &bi);
481 1.4 xtraeme if (rv)
482 1.4 xtraeme errx(EXIT_FAILURE, "BIOCINQ %s", strerror(errno));
483 1.1 bouyer
484 1.1 bouyer for (v = 0; v < bi.bi_novol; v++) {
485 1.1 bouyer memset(&bv, 0, sizeof(bv));
486 1.1 bouyer bv.bv_cookie = bl.bl_cookie;
487 1.1 bouyer bv.bv_volid = v;
488 1.2 xtraeme rv = ioctl(fd, BIOCVOL, &bv);
489 1.4 xtraeme if (rv == -1)
490 1.4 xtraeme errx(EXIT_FAILURE, "BIOCVOL %s", strerror(errno));
491 1.1 bouyer
492 1.1 bouyer for (d = 0; d < bv.bv_nodisk; d++) {
493 1.1 bouyer memset(&bd, 0, sizeof(bd));
494 1.1 bouyer bd.bd_cookie = bl.bl_cookie;
495 1.1 bouyer bd.bd_volid = v;
496 1.1 bouyer bd.bd_diskid = d;
497 1.1 bouyer
498 1.2 xtraeme rv = ioctl(fd, BIOCDISK, &bd);
499 1.4 xtraeme if (rv == -1)
500 1.4 xtraeme errx(EXIT_FAILURE, "BIOCDISK %s",
501 1.4 xtraeme strerror(errno));
502 1.1 bouyer
503 1.1 bouyer if (bd.bd_channel == location.channel &&
504 1.1 bouyer bd.bd_target == location.target &&
505 1.1 bouyer bd.bd_lun == location.lun) {
506 1.1 bouyer if (bd.bd_procdev[0] != '\0') {
507 1.2 xtraeme bio_blink(fd, bd.bd_procdev,
508 1.1 bouyer location.target, blink);
509 1.1 bouyer } else
510 1.1 bouyer warnx("Disk %s is not in an enclosure", arg);
511 1.1 bouyer return;
512 1.1 bouyer }
513 1.1 bouyer }
514 1.1 bouyer }
515 1.1 bouyer
516 1.1 bouyer warnx("Disk %s does not exist", arg);
517 1.1 bouyer return;
518 1.1 bouyer }
519 1.1 bouyer
520 1.2 xtraeme static void
521 1.2 xtraeme bio_blink(int fd, char *enclosure, int target, int blinktype)
522 1.1 bouyer {
523 1.1 bouyer struct bio_locate bio;
524 1.1 bouyer struct bioc_blink blink;
525 1.1 bouyer int rv;
526 1.1 bouyer
527 1.1 bouyer bio.bl_name = enclosure;
528 1.2 xtraeme rv = ioctl(fd, BIOCLOCATE, &bio);
529 1.1 bouyer if (rv == -1)
530 1.4 xtraeme errx(EXIT_FAILURE,
531 1.4 xtraeme "Can't locate %s device via %s", enclosure, "/dev/bio");
532 1.1 bouyer
533 1.1 bouyer memset(&blink, 0, sizeof(blink));
534 1.1 bouyer blink.bb_cookie = bio.bl_cookie;
535 1.1 bouyer blink.bb_status = blinktype;
536 1.1 bouyer blink.bb_target = target;
537 1.1 bouyer
538 1.2 xtraeme rv = ioctl(fd, BIOCBLINK, &blink);
539 1.1 bouyer if (rv == -1)
540 1.4 xtraeme errx(EXIT_FAILURE, "BIOCBLINK %s", strerror(errno));
541 1.1 bouyer }
542