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