1*7195049bSmarco /* $OpenBSD: bioctl.c,v 1.49 2007/03/19 03:02:09 marco Exp $ */ 2cf6503d7Sderaadt 33af9de98Smarco /* 42f39728eSdlg * Copyright (c) 2004, 2005 Marco Peereboom 53af9de98Smarco * All rights reserved. 63af9de98Smarco * 73af9de98Smarco * Redistribution and use in source and binary forms, with or without 83af9de98Smarco * modification, are permitted provided that the following conditions 93af9de98Smarco * are met: 103af9de98Smarco * 1. Redistributions of source code must retain the above copyright 113af9de98Smarco * notice, this list of conditions and the following disclaimer. 123af9de98Smarco * 2. Redistributions in binary form must reproduce the above copyright 133af9de98Smarco * notice, this list of conditions and the following disclaimer in the 143af9de98Smarco * documentation and/or other materials provided with the distribution. 153af9de98Smarco * 163af9de98Smarco * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 173af9de98Smarco * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 183af9de98Smarco * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 193af9de98Smarco * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR 203af9de98Smarco * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 213af9de98Smarco * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 223af9de98Smarco * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 233af9de98Smarco * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 243af9de98Smarco * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 253af9de98Smarco * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 263af9de98Smarco * SUCH DAMAGE. 273af9de98Smarco * 283af9de98Smarco */ 293af9de98Smarco 30c2126c9aSmarco #include <sys/ioctl.h> 31c2126c9aSmarco #include <sys/param.h> 32c2126c9aSmarco #include <sys/queue.h> 33c2126c9aSmarco #include <scsi/scsi_disk.h> 342b69df39Smarco #include <scsi/scsi_all.h> 353af9de98Smarco #include <dev/biovar.h> 363af9de98Smarco 37db2730c1Smarco #include <errno.h> 38db2730c1Smarco #include <err.h> 39db2730c1Smarco #include <fcntl.h> 408ccdd032Sderaadt #include <util.h> 41db2730c1Smarco #include <stdio.h> 42db2730c1Smarco #include <stdlib.h> 43db2730c1Smarco #include <string.h> 44db2730c1Smarco #include <unistd.h> 45e4e14ad7Sderaadt #include <ctype.h> 46db2730c1Smarco #include <util.h> 47db2730c1Smarco 486de960dcSmarco struct locator { 496de960dcSmarco int channel; 506de960dcSmarco int target; 516de960dcSmarco int lun; 526de960dcSmarco }; 536de960dcSmarco 548ccdd032Sderaadt void usage(void); 5541eccc89Sderaadt const char *str2locator(const char *, struct locator *); 568ccdd032Sderaadt void cleanup(void); 578ccdd032Sderaadt 588ccdd032Sderaadt void bio_inq(char *); 598ccdd032Sderaadt void bio_alarm(char *); 606de960dcSmarco void bio_setstate(char *); 61a928c459Sderaadt void bio_setblink(char *, char *, int); 62a928c459Sderaadt void bio_blink(char *, int, int); 63*7195049bSmarco void bio_createraid(u_int16_t, char *); 643af9de98Smarco 653af9de98Smarco int devh = -1; 66abe9d68eSderaadt int debug; 67abe9d68eSderaadt int human; 68abe9d68eSderaadt int verbose; 693af9de98Smarco 703af9de98Smarco struct bio_locate bl; 713af9de98Smarco 723af9de98Smarco int 733af9de98Smarco main(int argc, char *argv[]) 743af9de98Smarco { 753af9de98Smarco extern char *optarg; 76db2730c1Smarco u_int64_t func = 0; 77db2730c1Smarco /* u_int64_t subfunc = 0; */ 78cf6503d7Sderaadt char *bioc_dev = NULL, *sd_dev = NULL; 79cf6503d7Sderaadt char *realname = NULL, *al_arg = NULL; 80*7195049bSmarco char *bl_arg = NULL, *dev_list = NULL; 81a928c459Sderaadt int ch, rv, blink; 82*7195049bSmarco u_int16_t cr_level; 833af9de98Smarco 843af9de98Smarco if (argc < 2) 853af9de98Smarco usage(); 863af9de98Smarco 87*7195049bSmarco while ((ch = getopt(argc, argv, "b:c:l:u:H:ha:Div")) != -1) { 883af9de98Smarco switch (ch) { 89edfd9792Smarco case 'a': /* alarm */ 90edfd9792Smarco func |= BIOC_ALARM; 91edfd9792Smarco al_arg = optarg; 92edfd9792Smarco break; 93c55617f1Sdlg case 'b': /* blink */ 94c55617f1Sdlg func |= BIOC_BLINK; 95a928c459Sderaadt blink = BIOC_SBBLINK; 96a928c459Sderaadt bl_arg = optarg; 97a928c459Sderaadt break; 98*7195049bSmarco case 'c': /* create */ 99*7195049bSmarco func |= BIOC_CREATERAID; 100*7195049bSmarco cr_level = atoi(optarg); 101*7195049bSmarco break; 102a928c459Sderaadt case 'u': /* unblink */ 103a928c459Sderaadt func |= BIOC_BLINK; 104a928c459Sderaadt blink = BIOC_SBUNBLINK; 105c55617f1Sdlg bl_arg = optarg; 106c55617f1Sdlg break; 107db2730c1Smarco case 'D': /* debug */ 1083af9de98Smarco debug = 1; 1093af9de98Smarco break; 1106de960dcSmarco case 'H': /* set hotspare */ 1116de960dcSmarco func |= BIOC_SETSTATE; 1126de960dcSmarco al_arg = optarg; 1136de960dcSmarco break; 1148ccdd032Sderaadt case 'h': 1158ccdd032Sderaadt human = 1; 1168ccdd032Sderaadt break; 117db2730c1Smarco case 'i': /* inquiry */ 118db2730c1Smarco func |= BIOC_INQ; 1193af9de98Smarco break; 120*7195049bSmarco case 'l': /* device list */ 121*7195049bSmarco func |= BIOC_DEVLIST; 122*7195049bSmarco dev_list = optarg; 123*7195049bSmarco break; 124abe9d68eSderaadt case 'v': 125abe9d68eSderaadt verbose = 1; 126abe9d68eSderaadt break; 1273af9de98Smarco default: 1283af9de98Smarco usage(); 1293af9de98Smarco /* NOTREACHED */ 1303af9de98Smarco } 1313af9de98Smarco } 132cf6503d7Sderaadt argc -= optind; 133cf6503d7Sderaadt argv += optind; 1343af9de98Smarco 1358ccdd032Sderaadt if (argc != 1) 136cf6503d7Sderaadt usage(); 137cf6503d7Sderaadt 138dcbaf4c8Sderaadt if (func == 0) 139dcbaf4c8Sderaadt func |= BIOC_INQ; 140dcbaf4c8Sderaadt 141e4e14ad7Sderaadt /* if at least glob sd[0-9]*, it is a drive identifier */ 142e4e14ad7Sderaadt if (strncmp(argv[0], "sd", 2) == 0 && strlen(argv[0]) > 2 && 143e4e14ad7Sderaadt isdigit(argv[0][2])) 144cf6503d7Sderaadt sd_dev = argv[0]; 145cf6503d7Sderaadt else 146cf6503d7Sderaadt bioc_dev = argv[0]; 14710b411a7Smarco 14810b411a7Smarco if (bioc_dev) { 14941eccc89Sderaadt devh = open("/dev/bio", O_RDWR); 1503af9de98Smarco if (devh == -1) 15141eccc89Sderaadt err(1, "Can't open %s", "/dev/bio"); 1523af9de98Smarco 1538ccdd032Sderaadt bl.bl_name = bioc_dev; 1543af9de98Smarco rv = ioctl(devh, BIOCLOCATE, &bl); 1553af9de98Smarco if (rv == -1) 15610b411a7Smarco errx(1, "Can't locate %s device via %s", 15741eccc89Sderaadt bl.bl_name, "/dev/bio"); 158db2730c1Smarco } else if (sd_dev) { 15910b411a7Smarco devh = opendev(sd_dev, O_RDWR, OPENDEV_PART, &realname); 16010b411a7Smarco if (devh == -1) 16110b411a7Smarco err(1, "Can't open %s", sd_dev); 162db2730c1Smarco } else 16310b411a7Smarco errx(1, "need -d or -f parameter"); 1643af9de98Smarco 1653af9de98Smarco if (debug) 1668ccdd032Sderaadt warnx("cookie = %p", bl.bl_cookie); 1673af9de98Smarco 168db2730c1Smarco if (func & BIOC_INQ) { 1698ccdd032Sderaadt bio_inq(sd_dev); 170edfd9792Smarco } else if (func == BIOC_ALARM) { 171edfd9792Smarco bio_alarm(al_arg); 172c55617f1Sdlg } else if (func == BIOC_BLINK) { 173a928c459Sderaadt bio_setblink(sd_dev, bl_arg, blink); 1746de960dcSmarco } else if (func == BIOC_SETSTATE) { 1756de960dcSmarco bio_setstate(al_arg); 176*7195049bSmarco } else if (func & BIOC_CREATERAID || func & BIOC_DEVLIST) { 177*7195049bSmarco if (!(func & BIOC_CREATERAID)) 178*7195049bSmarco errx(1, "need -c parameter"); 179*7195049bSmarco if (!(func & BIOC_DEVLIST)) 180*7195049bSmarco errx(1, "need -l parameter"); 181*7195049bSmarco if (sd_dev) 182*7195049bSmarco errx(1, "can't use sd device"); 183*7195049bSmarco bio_createraid(cr_level, dev_list); 1843af9de98Smarco } 1853af9de98Smarco 1863af9de98Smarco return (0); 1873af9de98Smarco } 1883af9de98Smarco 1893af9de98Smarco void 1903af9de98Smarco usage(void) 1913af9de98Smarco { 1923af9de98Smarco extern char *__progname; 1933af9de98Smarco 194ebaf584eSderaadt fprintf(stderr, "usage: %s [-Dhiv] [-a alarm-function]" 19569e80e10Sderaadt " [[-bHu] chan:targ[.lun]] device\n", __progname); 1963af9de98Smarco exit(1); 1973af9de98Smarco } 1983af9de98Smarco 19941eccc89Sderaadt const char * 2006de960dcSmarco str2locator(const char *string, struct locator *location) 2016de960dcSmarco { 20250d3c4dcSdlg const char *errstr; 20341eccc89Sderaadt char parse[80], *targ, *lun; 2046de960dcSmarco 20541eccc89Sderaadt strlcpy(parse, string, sizeof parse); 20641eccc89Sderaadt targ = strchr(parse, ':'); 2076de960dcSmarco if (targ == NULL) 20841eccc89Sderaadt return ("target not specified"); 2096de960dcSmarco *targ++ = '\0'; 2106de960dcSmarco 21150d3c4dcSdlg lun = strchr(targ, '.'); 2126de960dcSmarco if (lun != NULL) { 2136de960dcSmarco *lun++ = '\0'; 21450d3c4dcSdlg location->lun = strtonum(lun, 0, 256, &errstr); 21550d3c4dcSdlg if (errstr) 21641eccc89Sderaadt return (errstr); 2176de960dcSmarco } else 2186de960dcSmarco location->lun = 0; 2196de960dcSmarco 22050d3c4dcSdlg location->target = strtonum(targ, 0, 256, &errstr); 22150d3c4dcSdlg if (errstr) 22241eccc89Sderaadt return (errstr); 22341eccc89Sderaadt location->channel = strtonum(parse, 0, 256, &errstr); 22450d3c4dcSdlg if (errstr) 22541eccc89Sderaadt return (errstr); 22641eccc89Sderaadt return (NULL); 2276de960dcSmarco } 2286de960dcSmarco 2293af9de98Smarco void 2308ccdd032Sderaadt bio_inq(char *name) 231d4546a56Sdlg { 2329017fb97Sderaadt char *status, size[64], scsiname[16], volname[32]; 233a4d3c4a2Sderaadt char percent[10], seconds[20]; 234b9950701Smarco int rv, i, d, volheader, hotspare, unused; 235aa65acf1Sderaadt char encname[16], serial[32]; 2368ccdd032Sderaadt struct bioc_disk bd; 2378ccdd032Sderaadt struct bioc_inq bi; 2388ccdd032Sderaadt struct bioc_vol bv; 239db2730c1Smarco 240db2730c1Smarco memset(&bi, 0, sizeof(bi)); 2413af9de98Smarco 2423af9de98Smarco if (debug) 243db2730c1Smarco printf("bio_inq\n"); 2443af9de98Smarco 2458ccdd032Sderaadt bi.bi_cookie = bl.bl_cookie; 2463af9de98Smarco 247db2730c1Smarco rv = ioctl(devh, BIOCINQ, &bi); 2483af9de98Smarco if (rv == -1) { 2497f33fb8fSderaadt warn("BIOCINQ"); 2503af9de98Smarco return; 2513af9de98Smarco } 2523af9de98Smarco 253a63b0c80Smarco if (debug) 254a63b0c80Smarco printf("bio_inq { %p, %s, %d, %d }\n", 255a63b0c80Smarco bi.bi_cookie, 256a63b0c80Smarco bi.bi_dev, 257a63b0c80Smarco bi.bi_novol, 258a63b0c80Smarco bi.bi_nodisk); 259a63b0c80Smarco 2608ccdd032Sderaadt volheader = 0; 2618ccdd032Sderaadt for (i = 0; i < bi.bi_novol; i++) { 262db2730c1Smarco memset(&bv, 0, sizeof(bv)); 2638ccdd032Sderaadt bv.bv_cookie = bl.bl_cookie; 2648ccdd032Sderaadt bv.bv_volid = i; 2650a92ff65Sderaadt bv.bv_percent = -1; 2669017fb97Sderaadt bv.bv_seconds = 0; 26770a2ae7bSmarco 268db2730c1Smarco rv = ioctl(devh, BIOCVOL, &bv); 2693af9de98Smarco if (rv == -1) { 2707f33fb8fSderaadt warn("BIOCVOL"); 2713af9de98Smarco return; 2723af9de98Smarco } 2733af9de98Smarco 2748ccdd032Sderaadt if (name && strcmp(name, bv.bv_dev) != 0) 2758ccdd032Sderaadt continue; 2768ccdd032Sderaadt 2778ccdd032Sderaadt if (!volheader) { 2788ccdd032Sderaadt volheader = 1; 279c9377e3bSmickey printf("%-7s %-10s %14s %-8s\n", 2808ccdd032Sderaadt "Volume", "Status", "Size", "Device"); 2818ccdd032Sderaadt } 2828ccdd032Sderaadt 2830a92ff65Sderaadt percent[0] = '\0'; 2849017fb97Sderaadt seconds[0] = '\0'; 2850a92ff65Sderaadt if (bv.bv_percent != -1) 2860a92ff65Sderaadt snprintf(percent, sizeof percent, 2870a92ff65Sderaadt " %d%% done", bv.bv_percent); 2889017fb97Sderaadt if (bv.bv_seconds) 2899017fb97Sderaadt snprintf(seconds, sizeof seconds, 2909017fb97Sderaadt " %u seconds", bv.bv_seconds); 2918ccdd032Sderaadt switch (bv.bv_status) { 292db2730c1Smarco case BIOC_SVONLINE: 2938ccdd032Sderaadt status = BIOC_SVONLINE_S; 294db2730c1Smarco break; 295db2730c1Smarco case BIOC_SVOFFLINE: 2968ccdd032Sderaadt status = BIOC_SVOFFLINE_S; 297db2730c1Smarco break; 298db2730c1Smarco case BIOC_SVDEGRADED: 2998ccdd032Sderaadt status = BIOC_SVDEGRADED_S; 300db2730c1Smarco break; 3010a92ff65Sderaadt case BIOC_SVBUILDING: 3020a92ff65Sderaadt status = BIOC_SVBUILDING_S; 3030a92ff65Sderaadt break; 3040a92ff65Sderaadt case BIOC_SVREBUILD: 3050a92ff65Sderaadt status = BIOC_SVREBUILD_S; 3060a92ff65Sderaadt break; 3070a92ff65Sderaadt case BIOC_SVSCRUB: 3080a92ff65Sderaadt status = BIOC_SVSCRUB_S; 3090a92ff65Sderaadt break; 310db2730c1Smarco case BIOC_SVINVALID: 311db2730c1Smarco default: 3128ccdd032Sderaadt status = BIOC_SVINVALID_S; 313d4546a56Sdlg } 3143af9de98Smarco 315aa65acf1Sderaadt snprintf(volname, sizeof volname, "%s %u", 3168ccdd032Sderaadt bi.bi_dev, bv.bv_volid); 317b9950701Smarco 318aa65acf1Sderaadt if (bv.bv_level == -1 && bv.bv_nodisk == 1) 319aa65acf1Sderaadt hotspare = 1; 320b9950701Smarco else if (bv.bv_level == -2 && bv.bv_nodisk == 1) 321b9950701Smarco unused = 1; 322aa65acf1Sderaadt else { 323b9950701Smarco unused = 0; 324aa65acf1Sderaadt hotspare = 0; 325aa65acf1Sderaadt 3268ccdd032Sderaadt if (human) 3278ccdd032Sderaadt fmt_scaled(bv.bv_size, size); 3288ccdd032Sderaadt else 3298ccdd032Sderaadt snprintf(size, sizeof size, "%14llu", 3308ccdd032Sderaadt bv.bv_size); 3319017fb97Sderaadt printf("%7s %-10s %14s %-7s RAID%u%s%s\n", 3320a92ff65Sderaadt volname, status, size, bv.bv_dev, 3339017fb97Sderaadt bv.bv_level, percent, seconds); 334aa65acf1Sderaadt } 3358ccdd032Sderaadt 3368ccdd032Sderaadt for (d = 0; d < bv.bv_nodisk; d++) { 337db2730c1Smarco memset(&bd, 0, sizeof(bd)); 3388ccdd032Sderaadt bd.bd_cookie = bl.bl_cookie; 3398ccdd032Sderaadt bd.bd_diskid = d; 3408ccdd032Sderaadt bd.bd_volid = i; 3413af9de98Smarco 342db2730c1Smarco rv = ioctl(devh, BIOCDISK, &bd); 3433af9de98Smarco if (rv == -1) { 3447f33fb8fSderaadt warn("BIOCDISK"); 3453af9de98Smarco return; 3463af9de98Smarco } 3473af9de98Smarco 3488ccdd032Sderaadt switch (bd.bd_status) { 349db2730c1Smarco case BIOC_SDONLINE: 3508ccdd032Sderaadt status = BIOC_SDONLINE_S; 351d4546a56Sdlg break; 352db2730c1Smarco case BIOC_SDOFFLINE: 3538ccdd032Sderaadt status = BIOC_SDOFFLINE_S; 354d4546a56Sdlg break; 355db2730c1Smarco case BIOC_SDFAILED: 3568ccdd032Sderaadt status = BIOC_SDFAILED_S; 357db2730c1Smarco break; 358db2730c1Smarco case BIOC_SDREBUILD: 3598ccdd032Sderaadt status = BIOC_SDREBUILD_S; 360db2730c1Smarco break; 361db2730c1Smarco case BIOC_SDHOTSPARE: 3628ccdd032Sderaadt status = BIOC_SDHOTSPARE_S; 363db2730c1Smarco break; 364db2730c1Smarco case BIOC_SDUNUSED: 3658ccdd032Sderaadt status = BIOC_SDUNUSED_S; 366db2730c1Smarco break; 367e1dfb373Sderaadt case BIOC_SDSCRUB: 368e1dfb373Sderaadt status = BIOC_SDSCRUB_S; 369e1dfb373Sderaadt break; 370db2730c1Smarco case BIOC_SDINVALID: 371d4546a56Sdlg default: 3728ccdd032Sderaadt status = BIOC_SDINVALID_S; 373d4546a56Sdlg } 374aa65acf1Sderaadt 375b9950701Smarco if (hotspare || unused) 376aa65acf1Sderaadt ; /* use volname from parent volume */ 377aa65acf1Sderaadt else 378aa65acf1Sderaadt snprintf(volname, sizeof volname, " %3u", 379aa65acf1Sderaadt bd.bd_diskid); 380aa65acf1Sderaadt 3818ccdd032Sderaadt if (human) 3828ccdd032Sderaadt fmt_scaled(bd.bd_size, size); 3838ccdd032Sderaadt else 3848ccdd032Sderaadt snprintf(size, sizeof size, "%14llu", 3858ccdd032Sderaadt bd.bd_size); 3868ccdd032Sderaadt snprintf(scsiname, sizeof scsiname, 38743d61178Sderaadt "%u:%u.%u", 38843d61178Sderaadt bd.bd_channel, bd.bd_target, bd.bd_lun); 3895978b28dSderaadt if (bd.bd_procdev[0]) 390abe9d68eSderaadt strlcpy(encname, bd.bd_procdev, sizeof encname); 3915978b28dSderaadt else 392abe9d68eSderaadt strlcpy(encname, "noencl", sizeof encname); 393abe9d68eSderaadt if (bd.bd_serial[0]) 394abe9d68eSderaadt strlcpy(serial, bd.bd_serial, sizeof serial); 395abe9d68eSderaadt else 396abe9d68eSderaadt strlcpy(serial, "unknown serial", sizeof serial); 3978ccdd032Sderaadt 398aa65acf1Sderaadt printf("%7s %-10s %14s %-7s %-6s <%s>\n", 399aa65acf1Sderaadt volname, status, size, scsiname, encname, 4008ccdd032Sderaadt bd.bd_vendor); 401abe9d68eSderaadt if (verbose) 402aa65acf1Sderaadt printf("%7s %-10s %14s %-7s %-6s '%s'\n", 403abe9d68eSderaadt "", "", "", "", "", serial); 404d4546a56Sdlg } 405d4546a56Sdlg } 406d4546a56Sdlg } 407edfd9792Smarco 408edfd9792Smarco void 409edfd9792Smarco bio_alarm(char *arg) 410edfd9792Smarco { 411edfd9792Smarco int rv; 4128ccdd032Sderaadt struct bioc_alarm ba; 413edfd9792Smarco 4148ccdd032Sderaadt ba.ba_cookie = bl.bl_cookie; 415edfd9792Smarco 416edfd9792Smarco switch (arg[0]) { 417edfd9792Smarco case 'q': /* silence alarm */ 418edfd9792Smarco /* FALLTHROUGH */ 419edfd9792Smarco case 's': 4208ccdd032Sderaadt ba.ba_opcode = BIOC_SASILENCE; 421edfd9792Smarco break; 422edfd9792Smarco 423edfd9792Smarco case 'e': /* enable alarm */ 4248ccdd032Sderaadt ba.ba_opcode = BIOC_SAENABLE; 425edfd9792Smarco break; 426edfd9792Smarco 427edfd9792Smarco case 'd': /* disable alarm */ 4288ccdd032Sderaadt ba.ba_opcode = BIOC_SADISABLE; 429edfd9792Smarco break; 430edfd9792Smarco 431edfd9792Smarco case 't': /* test alarm */ 4328ccdd032Sderaadt ba.ba_opcode = BIOC_SATEST; 433edfd9792Smarco break; 434edfd9792Smarco 435edfd9792Smarco case 'g': /* get alarm state */ 4368ccdd032Sderaadt ba.ba_opcode = BIOC_GASTATUS; 437edfd9792Smarco break; 438edfd9792Smarco 439edfd9792Smarco default: 440edfd9792Smarco warnx("invalid alarm function: %s", arg); 441edfd9792Smarco return; 442edfd9792Smarco } 443edfd9792Smarco 444edfd9792Smarco rv = ioctl(devh, BIOCALARM, &ba); 445edfd9792Smarco if (rv == -1) { 4467f33fb8fSderaadt warn("BIOCALARM"); 447edfd9792Smarco return; 448edfd9792Smarco } 449edfd9792Smarco 450edfd9792Smarco if (arg[0] == 'g') { 451edfd9792Smarco printf("alarm is currently %s\n", 4528ccdd032Sderaadt ba.ba_status ? "enabled" : "disabled"); 4538ccdd032Sderaadt 454edfd9792Smarco } 455edfd9792Smarco } 4566de960dcSmarco 457ebaf584eSderaadt void 458ebaf584eSderaadt bio_setstate(char *arg) 4596de960dcSmarco { 4606de960dcSmarco struct bioc_setstate bs; 4616de960dcSmarco struct locator location; 46241eccc89Sderaadt const char *errstr; 463ebaf584eSderaadt int rv; 4646de960dcSmarco 46541eccc89Sderaadt errstr = str2locator(arg, &location); 46641eccc89Sderaadt if (errstr) 46741eccc89Sderaadt errx(1, "Target %s: %s", arg, errstr); 4686de960dcSmarco 4696de960dcSmarco bs.bs_cookie = bl.bl_cookie; 4706de960dcSmarco bs.bs_status = BIOC_SSHOTSPARE; 4716de960dcSmarco bs.bs_channel = location.channel; 4726de960dcSmarco bs.bs_target = location.target; 4736de960dcSmarco bs.bs_lun = location.lun; 4746de960dcSmarco 4756de960dcSmarco rv = ioctl(devh, BIOCSETSTATE, &bs); 4766de960dcSmarco if (rv == -1) { 4777f33fb8fSderaadt warn("BIOCSETSTATE"); 4786de960dcSmarco return; 4796de960dcSmarco } 4806de960dcSmarco } 481c55617f1Sdlg 482c55617f1Sdlg void 483a928c459Sderaadt bio_setblink(char *name, char *arg, int blink) 484c55617f1Sdlg { 48550d3c4dcSdlg struct locator location; 48650d3c4dcSdlg struct bioc_inq bi; 48750d3c4dcSdlg struct bioc_vol bv; 48850d3c4dcSdlg struct bioc_disk bd; 4890505205bSdlg struct bioc_blink bb; 49041eccc89Sderaadt const char *errstr; 49150d3c4dcSdlg int v, d, rv; 492c55617f1Sdlg 49341eccc89Sderaadt errstr = str2locator(arg, &location); 49441eccc89Sderaadt if (errstr) 49541eccc89Sderaadt errx(1, "Target %s: %s", arg, errstr); 49650d3c4dcSdlg 4970505205bSdlg /* try setting blink on the device directly */ 4980505205bSdlg memset(&bb, 0, sizeof(bb)); 4990505205bSdlg bb.bb_cookie = bl.bl_cookie; 5000505205bSdlg bb.bb_status = blink; 5010505205bSdlg bb.bb_target = location.target; 502649724a4Smarco bb.bb_channel = location.channel; 5030505205bSdlg rv = ioctl(devh, BIOCBLINK, &bb); 5040505205bSdlg if (rv == 0) 5050505205bSdlg return; 5060505205bSdlg 5070505205bSdlg /* if the blink didnt work, try to find something that will */ 5080505205bSdlg 50950d3c4dcSdlg memset(&bi, 0, sizeof(bi)); 51050d3c4dcSdlg bi.bi_cookie = bl.bl_cookie; 51150d3c4dcSdlg rv = ioctl(devh, BIOCINQ, &bi); 51250d3c4dcSdlg if (rv == -1) { 5137f33fb8fSderaadt warn("BIOCINQ"); 51450d3c4dcSdlg return; 51550d3c4dcSdlg } 51650d3c4dcSdlg 51750d3c4dcSdlg for (v = 0; v < bi.bi_novol; v++) { 51850d3c4dcSdlg memset(&bv, 0, sizeof(bv)); 51950d3c4dcSdlg bv.bv_cookie = bl.bl_cookie; 52050d3c4dcSdlg bv.bv_volid = v; 52150d3c4dcSdlg rv = ioctl(devh, BIOCVOL, &bv); 52250d3c4dcSdlg if (rv == -1) { 5237f33fb8fSderaadt warn("BIOCVOL"); 52450d3c4dcSdlg return; 52550d3c4dcSdlg } 52650d3c4dcSdlg 52750d3c4dcSdlg if (name && strcmp(name, bv.bv_dev) != 0) 52850d3c4dcSdlg continue; 52950d3c4dcSdlg 53050d3c4dcSdlg for (d = 0; d < bv.bv_nodisk; d++) { 53150d3c4dcSdlg memset(&bd, 0, sizeof(bd)); 53250d3c4dcSdlg bd.bd_cookie = bl.bl_cookie; 53350d3c4dcSdlg bd.bd_volid = v; 53450d3c4dcSdlg bd.bd_diskid = d; 53550d3c4dcSdlg 53650d3c4dcSdlg rv = ioctl(devh, BIOCDISK, &bd); 53750d3c4dcSdlg if (rv == -1) { 5387f33fb8fSderaadt warn("BIOCDISK"); 53950d3c4dcSdlg return; 54050d3c4dcSdlg } 54150d3c4dcSdlg 54250d3c4dcSdlg if (bd.bd_channel == location.channel && 54350d3c4dcSdlg bd.bd_target == location.target && 54450d3c4dcSdlg bd.bd_lun == location.lun) { 54550d3c4dcSdlg if (bd.bd_procdev[0] != '\0') { 54650d3c4dcSdlg bio_blink(bd.bd_procdev, 547a928c459Sderaadt location.target, blink); 54850d3c4dcSdlg } else 54941eccc89Sderaadt warnx("Disk %s is not in an enclosure", arg); 55050d3c4dcSdlg return; 55150d3c4dcSdlg } 55250d3c4dcSdlg } 55350d3c4dcSdlg } 55450d3c4dcSdlg 55541eccc89Sderaadt warnx("Disk %s does not exist", arg); 55650d3c4dcSdlg return; 55750d3c4dcSdlg } 55850d3c4dcSdlg 55950d3c4dcSdlg void 560a928c459Sderaadt bio_blink(char *enclosure, int target, int blinktype) 56150d3c4dcSdlg { 56250d3c4dcSdlg int bioh; 56350d3c4dcSdlg struct bio_locate bio; 56450d3c4dcSdlg struct bioc_blink blink; 56550d3c4dcSdlg int rv; 56650d3c4dcSdlg 56741eccc89Sderaadt bioh = open("/dev/bio", O_RDWR); 56850d3c4dcSdlg if (bioh == -1) 56941eccc89Sderaadt err(1, "Can't open %s", "/dev/bio"); 57050d3c4dcSdlg 57150d3c4dcSdlg bio.bl_name = enclosure; 57250d3c4dcSdlg rv = ioctl(bioh, BIOCLOCATE, &bio); 57350d3c4dcSdlg if (rv == -1) 57441eccc89Sderaadt errx(1, "Can't locate %s device via %s", enclosure, "/dev/bio"); 575c55617f1Sdlg 576c55617f1Sdlg memset(&blink, 0, sizeof(blink)); 57750d3c4dcSdlg blink.bb_cookie = bio.bl_cookie; 578a928c459Sderaadt blink.bb_status = blinktype; 579c55617f1Sdlg blink.bb_target = target; 580c55617f1Sdlg 58150d3c4dcSdlg rv = ioctl(bioh, BIOCBLINK, &blink); 582c55617f1Sdlg if (rv == -1) 5837f33fb8fSderaadt warn("BIOCBLINK"); 58450d3c4dcSdlg 58550d3c4dcSdlg close(bioh); 586c55617f1Sdlg } 587*7195049bSmarco 588*7195049bSmarco void 589*7195049bSmarco bio_createraid(u_int16_t level, char *dev_list) 590*7195049bSmarco { 591*7195049bSmarco struct bio_locate bio; 592*7195049bSmarco struct bioc_createraid create; 593*7195049bSmarco int rv; 594*7195049bSmarco u_int16_t min_disks = 0; 595*7195049bSmarco 596*7195049bSmarco if (debug) 597*7195049bSmarco printf("bio_createraid\n"); 598*7195049bSmarco 599*7195049bSmarco if (!dev_list) 600*7195049bSmarco errx(1, "no devices specified"); 601*7195049bSmarco 602*7195049bSmarco switch (level) { 603*7195049bSmarco case 0: 604*7195049bSmarco min_disks = 1; 605*7195049bSmarco break; 606*7195049bSmarco case 1: 607*7195049bSmarco min_disks = 2; 608*7195049bSmarco break; 609*7195049bSmarco default: 610*7195049bSmarco errx(1, "unsuported raid level"); 611*7195049bSmarco } 612*7195049bSmarco 613*7195049bSmarco /* XXX validate device list for real */ 614*7195049bSmarco #if 0 615*7195049bSmarco if (strncmp(dev_list, "sd", 2) == 0 && strlen(dev_list) > 2 && 616*7195049bSmarco isdigit(dev_list[2])) { 617*7195049bSmarco if (strlen(dev_list) != 3) 618*7195049bSmarco errx(1, "only one device supported"); 619*7195049bSmarco 620*7195049bSmarco if (debug) 621*7195049bSmarco printf("bio_createraid: dev_list: %s\n", dev_list); 622*7195049bSmarco } 623*7195049bSmarco else 624*7195049bSmarco errx(1, "no sd device specified"); 625*7195049bSmarco #endif 626*7195049bSmarco 627*7195049bSmarco memset(&create, 0, sizeof(create)); 628*7195049bSmarco create.bc_cookie = bl.bl_cookie; 629*7195049bSmarco create.bc_level = level; 630*7195049bSmarco create.bc_dev_list_len = strlen(dev_list); 631*7195049bSmarco create.bc_dev_list = dev_list; 632*7195049bSmarco 633*7195049bSmarco rv = ioctl(devh, BIOCCREATERAID, &create); 634*7195049bSmarco if (rv == -1) { 635*7195049bSmarco warn("BIOCCREATERAID"); 636*7195049bSmarco return; 637*7195049bSmarco } 638*7195049bSmarco } 639