Example #1
0
void
bio_blink(char *enclosure, int target, int blinktype)
{
    int			bioh;
    struct bio_locate	bl;
    struct bioc_blink	blink;

    bioh = open("/dev/bio", O_RDWR);
    if (bioh == -1)
        err(1, "Can't open %s", "/dev/bio");

    memset(&bl, 0, sizeof(bl));
    bl.bl_name = enclosure;
    if (ioctl(bioh, BIOCLOCATE, &bl))
        errx(1, "Can't locate %s device via %s", enclosure, "/dev/bio");

    bio_status(&bl.bl_bio.bio_status);

    memset(&blink, 0, sizeof(blink));
    blink.bb_bio.bio_cookie = bio_cookie;
    blink.bb_status = blinktype;
    blink.bb_target = target;

    if (ioctl(bioh, BIOCBLINK, &blink))
        err(1, "BIOCBLINK");

    bio_status(&blink.bb_bio.bio_status);

    close(bioh);
}
Example #2
0
int
bio_getvolbyname(char *name)
{
    int			id = -1, i;
    struct bioc_inq		bi;
    struct bioc_vol		bv;

    memset(&bi, 0, sizeof(bi));
    bi.bi_bio.bio_cookie = bio_cookie;
    if (ioctl(devh, BIOCINQ, &bi))
        err(1, "BIOCINQ");

    bio_status(&bi.bi_bio.bio_status);

    for (i = 0; i < bi.bi_novol; i++) {
        memset(&bv, 0, sizeof(bv));
        bv.bv_bio.bio_cookie = bio_cookie;
        bv.bv_volid = i;
        if (ioctl(devh, BIOCVOL, &bv))
            err(1, "BIOCVOL");

        bio_status(&bv.bv_bio.bio_status);

        if (name && strcmp(name, bv.bv_dev) != 0)
            continue;
        id = i;
        break;
    }

    return (id);
}
Example #3
0
void
bio_changepass(char *dev)
{
    struct bioc_discipline bd;
    struct sr_crypto_kdfpair kdfpair;
    struct sr_crypto_kdfinfo kdfinfo1, kdfinfo2;
    struct sr_crypto_kdf_pbkdf2 kdfhint;
    int rv;

    memset(&bd, 0, sizeof(bd));
    memset(&kdfhint, 0, sizeof(kdfhint));
    memset(&kdfinfo1, 0, sizeof(kdfinfo1));
    memset(&kdfinfo2, 0, sizeof(kdfinfo2));

    /* XXX use dev_t instead of string. */
    strlcpy(bd.bd_dev, dev, sizeof(bd.bd_dev));
    bd.bd_cmd = SR_IOCTL_GET_KDFHINT;
    bd.bd_size = sizeof(kdfhint);
    bd.bd_data = &kdfhint;

    if (ioctl(devh, BIOCDISCIPLINE, &bd))
        err(1, "BIOCDISCIPLINE");

    bio_status(&bd.bd_bio.bio_status);

    /* Current passphrase. */
    bio_kdf_derive(&kdfinfo1, &kdfhint, "Old passphrase: ", 0);

    /* New passphrase. */
    bio_kdf_derive(&kdfinfo2, &kdfhint, "New passphrase: ", 1);

    kdfpair.kdfinfo1 = &kdfinfo1;
    kdfpair.kdfsize1 = sizeof(kdfinfo1);
    kdfpair.kdfinfo2 = &kdfinfo2;
    kdfpair.kdfsize2 = sizeof(kdfinfo2);

    bd.bd_cmd = SR_IOCTL_CHANGE_PASSPHRASE;
    bd.bd_size = sizeof(kdfpair);
    bd.bd_data = &kdfpair;

    rv = ioctl(devh, BIOCDISCIPLINE, &bd);

    memset(&kdfhint, 0, sizeof(kdfhint));
    memset(&kdfinfo1, 0, sizeof(kdfinfo1));
    memset(&kdfinfo2, 0, sizeof(kdfinfo2));

    if (rv)
        err(1, "BIOCDISCIPLINE");

    bio_status(&bd.bd_bio.bio_status);
}
Example #4
0
void
bio_error(struct bio_status *bs, int print, const char *fmt, ...)
{
	va_list	ap;

	va_start(ap, fmt);
	bio_status(bs, print, BIO_MSG_ERROR, fmt, &ap);
	va_end(ap);
}
Example #5
0
void
bio_warn(struct bio_status *bs, int print, const char *fmt, ...)
{
	va_list	ap;

	va_start(ap, fmt);
	bio_status(bs, print, BIO_MSG_WARN, fmt, &ap);
	va_end(ap);
}
Example #6
0
void
bio_deleteraid(char *dev)
{
    struct bioc_deleteraid	bd;
    memset(&bd, 0, sizeof(bd));

    bd.bd_bio.bio_cookie = bio_cookie;
    /* XXX make this a dev_t instead of a string */
    strlcpy(bd.bd_dev, dev, sizeof bd.bd_dev);
    if (ioctl(devh, BIOCDELETERAID, &bd))
        err(1, "BIOCDELETERAID");

    bio_status(&bd.bd_bio.bio_status);
}
Example #7
0
void
bio_alarm(char *arg)
{
    struct bioc_alarm	ba;

    memset(&ba, 0, sizeof(ba));
    ba.ba_bio.bio_cookie = bio_cookie;

    switch (arg[0]) {
    case 'q': /* silence alarm */
    /* FALLTHROUGH */
    case 's':
        ba.ba_opcode = BIOC_SASILENCE;
        break;

    case 'e': /* enable alarm */
        ba.ba_opcode = BIOC_SAENABLE;
        break;

    case 'd': /* disable alarm */
        ba.ba_opcode = BIOC_SADISABLE;
        break;

    case 't': /* test alarm */
        ba.ba_opcode = BIOC_SATEST;
        break;

    case 'g': /* get alarm state */
        ba.ba_opcode = BIOC_GASTATUS;
        break;

    default:
        errx(1, "invalid alarm function: %s", arg);
    }

    if (ioctl(devh, BIOCALARM, &ba))
        err(1, "BIOCALARM");

    bio_status(&ba.ba_bio.bio_status);

    if (arg[0] == 'g')
        printf("alarm is currently %s\n",
               ba.ba_status ? "enabled" : "disabled");
}
Example #8
0
void
bio_setstate(char *arg, int status, char *devicename)
{
    struct bioc_setstate	bs;
    struct locator		location;
    struct stat		sb;
    const char		*errstr;

    memset(&bs, 0, sizeof(bs));
    if (stat(arg, &sb) == -1) {
        /* use CTL */
        errstr = str2locator(arg, &location);
        if (errstr)
            errx(1, "Target %s: %s", arg, errstr);
        bs.bs_channel = location.channel;
        bs.bs_target = location.target;
        bs.bs_lun = location.lun;
    } else {
        /* use other id */
        bs.bs_other_id = sb.st_rdev;
        bs.bs_other_id_type = BIOC_SSOTHER_DEVT;
    }

    bs.bs_bio.bio_cookie = bio_cookie;
    bs.bs_status = status;

    if (status != BIOC_SSHOTSPARE) {
        /* make sure user supplied a sd device */
        bs.bs_volid = bio_getvolbyname(devicename);
        if (bs.bs_volid == -1)
            errx(1, "invalid device %s", devicename);
    }

    if (ioctl(devh, BIOCSETSTATE, &bs))
        err(1, "BIOCSETSTATE");

    bio_status(&bs.bs_bio.bio_status);
}
Example #9
0
int
main(int argc, char *argv[])
{
    struct bio_locate	bl;
    extern char		*optarg;
    u_int64_t		func = 0;
    char			*devicename = NULL;
    char			*realname = NULL, *al_arg = NULL;
    char			*bl_arg = NULL, *dev_list = NULL;
    char			*key_disk = NULL;
    const char		*errstr;
    int			ch, blink = 0, changepass = 0, diskinq = 0;
    int			ss_func = 0;
    u_int16_t		cr_level = 0;
    int			biodev = 0;

    if (argc < 2)
        usage();

    while ((ch = getopt(argc, argv, "a:b:C:c:dH:hik:l:O:Pp:qr:R:svu:")) !=
            -1) {
        switch (ch) {
        case 'a': /* alarm */
            func |= BIOC_ALARM;
            al_arg = optarg;
            break;
        case 'b': /* blink */
            func |= BIOC_BLINK;
            blink = BIOC_SBBLINK;
            bl_arg = optarg;
            break;
        case 'C': /* creation flags */
            cflags = bio_createflags(optarg);
            break;
        case 'c': /* create */
            func |= BIOC_CREATERAID;
            if (isdigit((unsigned char)*optarg)) {
                cr_level = strtonum(optarg, 0, 10, &errstr);
                if (errstr != NULL)
                    errx(1, "Invalid RAID level");
            } else
                cr_level = *optarg;
            break;
        case 'd':
            /* delete volume */
            func |= BIOC_DELETERAID;
            break;
        case 'u': /* unblink */
            func |= BIOC_BLINK;
            blink = BIOC_SBUNBLINK;
            bl_arg = optarg;
            break;
        case 'H': /* set hotspare */
            func |= BIOC_SETSTATE;
            ss_func = BIOC_SSHOTSPARE;
            al_arg = optarg;
            break;
        case 'h':
            human = 1;
            break;
        case 'i': /* inquiry */
            func |= BIOC_INQ;
            break;
        case 'k': /* Key disk. */
            key_disk = optarg;
            break;
        case 'l': /* device list */
            func |= BIOC_DEVLIST;
            dev_list = optarg;
            break;
        case 'P':
            /* Change passphrase. */
            changepass = 1;
            break;
        case 'p':
            password = optarg;
            break;
        case 'r':
            rflag = strtonum(optarg, 1000, 1<<30, &errstr);
            if (errstr != NULL)
                errx(1, "Number of rounds is %s: %s",
                     errstr, optarg);
            break;
        case 'O':
            /* set a chunk to offline */
            func |= BIOC_SETSTATE;
            ss_func = BIOC_SSOFFLINE;
            al_arg = optarg;
            break;
        case 'R':
            /* rebuild to provided chunk/CTL */
            func |= BIOC_SETSTATE;
            ss_func = BIOC_SSREBUILD;
            al_arg = optarg;
            break;
        case 's':
            rpp_flag = RPP_STDIN;
            break;
        case 'v':
            verbose = 1;
            break;
        case 'q':
            diskinq = 1;
            break;
        default:
            usage();
            /* NOTREACHED */
        }
    }
    argc -= optind;
    argv += optind;

    if (argc != 1 || (changepass && func != 0))
        usage();

    if (func == 0)
        func |= BIOC_INQ;

    devicename = argv[0];
    if (devicename == NULL)
        errx(1, "need device");

    devh = opendev(devicename, O_RDWR, OPENDEV_PART, &realname);
    if (devh == -1) {
        devh = open("/dev/bio", O_RDWR);
        if (devh == -1)
            err(1, "Can't open %s", "/dev/bio");

        bl.bl_name = devicename;
        if (ioctl(devh, BIOCLOCATE, &bl))
            errx(1, "Can't locate %s device via %s",
                 bl.bl_name, "/dev/bio");

        bio_status(&bl.bl_bio.bio_status);

        bio_cookie = bl.bl_bio.bio_cookie;
        biodev = 1;
        devicename = NULL;
    }

    if (diskinq) {
        bio_diskinq(devicename);
    } else if (changepass && !biodev) {
        bio_changepass(devicename);
    } else if (func & BIOC_INQ) {
        bio_inq(devicename);
    } else if (func == BIOC_ALARM) {
        bio_alarm(al_arg);
    } else if (func == BIOC_BLINK) {
        bio_setblink(devicename, bl_arg, blink);
    } else if (func == BIOC_SETSTATE) {
        bio_setstate(al_arg, ss_func, argv[0]);
    } else if (func == BIOC_DELETERAID && !biodev) {
        bio_deleteraid(devicename);
    } else if (func & BIOC_CREATERAID || func & BIOC_DEVLIST) {
        if (!(func & BIOC_CREATERAID))
            errx(1, "need -c parameter");
        if (!(func & BIOC_DEVLIST))
            errx(1, "need -l parameter");
        if (!biodev)
            errx(1, "must use bio device");
        bio_createraid(cr_level, dev_list, key_disk);
    }

    return (0);
}
Example #10
0
void
bio_createraid(u_int16_t level, char *dev_list, char *key_disk)
{
    struct bioc_createraid	create;
    struct sr_crypto_kdfinfo kdfinfo;
    struct sr_crypto_kdf_pbkdf2 kdfhint;
#ifdef AOE
    struct sr_aoe_config	*sac;
#endif /* AOE */
    struct stat		sb;
    int			rv, no_dev, fd;
    dev_t			*dt;
    u_int16_t		min_disks = 0;

    if (!dev_list)
        errx(1, "no devices specified");

#ifdef AOE
    if (level == 'a') {
        sac = create_aoe(level, dev_list);
        no_dev = 0;
        dt = NULL;
    } else
#endif /* AOE */
    {
        dt = calloc(1, BIOC_CRMAXLEN);
        if (!dt)
            err(1, "not enough memory for dev_t list");

        no_dev = bio_parse_devlist(dev_list, dt);
    }

    switch (level) {
    case 0:
        min_disks = 2;
        break;
    case 1:
        min_disks = 2;
        break;
#ifdef RAID5
    case 5:
        min_disks = 3;
        break;
#endif /* RAID5 */
    case 'C':
        min_disks = 1;
        break;
    case 'c':
        min_disks = 2;
        break;
#ifdef AOE
    case 'a':
        break;
#endif /* AOE */
    default:
        errx(1, "unsupported raid level");
    }

    if (no_dev < min_disks)
        errx(1, "not enough disks");

    /* for crypto raid we only allow one single chunk */
    if (level == 'C' && no_dev != min_disks)
        errx(1, "not exactly one partition");

    memset(&create, 0, sizeof(create));
    create.bc_bio.bio_cookie = bio_cookie;
    create.bc_level = level;
    create.bc_dev_list_len = no_dev * sizeof(dev_t);
    create.bc_dev_list = dt;
    create.bc_flags = BIOC_SCDEVT | cflags;
    create.bc_key_disk = NODEV;

#ifdef AOE
    if (level == 'a') {
        create.bc_opaque = sac;
        create.bc_opaque_size = sizeof(*sac);
        create.bc_opaque_flags = BIOC_SOIN;
    } else
#endif /* AOE */
        if (level == 'C' && key_disk == NULL) {

            memset(&kdfinfo, 0, sizeof(kdfinfo));
            memset(&kdfhint, 0, sizeof(kdfhint));

            create.bc_flags |= BIOC_SCNOAUTOASSEMBLE;

            create.bc_opaque = &kdfhint;
            create.bc_opaque_size = sizeof(kdfhint);
            create.bc_opaque_flags = BIOC_SOOUT;

            /* try to get KDF hint */
            if (ioctl(devh, BIOCCREATERAID, &create))
                err(1, "ioctl");

            bio_status(&create.bc_bio.bio_status);

            if (create.bc_opaque_status == BIOC_SOINOUT_OK) {
                bio_kdf_derive(&kdfinfo, &kdfhint, "Passphrase: ", 0);
                memset(&kdfhint, 0, sizeof(kdfhint));
            } else {
                bio_kdf_generate(&kdfinfo);
            }

            create.bc_opaque = &kdfinfo;
            create.bc_opaque_size = sizeof(kdfinfo);
            create.bc_opaque_flags = BIOC_SOIN;

        } else if (level == 'C' && key_disk != NULL) {

            /* Get device number for key disk. */
            fd = opendev(key_disk, O_RDONLY, OPENDEV_BLCK, NULL);
            if (fd == -1)
                err(1, "could not open %s", key_disk);
            if (fstat(fd, &sb) == -1) {
                close(fd);
                err(1, "could not stat %s", key_disk);
            }
            close(fd);
            create.bc_key_disk = sb.st_rdev;

            memset(&kdfinfo, 0, sizeof(kdfinfo));

            kdfinfo.genkdf.len = sizeof(kdfinfo.genkdf);
            kdfinfo.genkdf.type = SR_CRYPTOKDFT_KEYDISK;
            kdfinfo.len = sizeof(kdfinfo);
            kdfinfo.flags = SR_CRYPTOKDF_HINT;

            create.bc_opaque = &kdfinfo;
            create.bc_opaque_size = sizeof(kdfinfo);
            create.bc_opaque_flags = BIOC_SOIN;

        }

    rv = ioctl(devh, BIOCCREATERAID, &create);
    memset(&kdfinfo, 0, sizeof(kdfinfo));
    if (rv == -1)
        err(1, "BIOCCREATERAID");

    bio_status(&create.bc_bio.bio_status);

    free(dt);
}
Example #11
0
void
bio_setblink(char *name, char *arg, int blink)
{
    struct locator		location;
    struct bioc_blink	bb;
    struct bioc_inq		bi;
    struct bioc_vol		bv;
    struct bioc_disk	bd;
    const char		*errstr;
    int			v, d, rv;

    errstr = str2locator(arg, &location);
    if (errstr)
        errx(1, "Target %s: %s", arg, errstr);

    /* try setting blink on the device directly */
    memset(&bb, 0, sizeof(bb));
    bb.bb_bio.bio_cookie = bio_cookie;
    bb.bb_status = blink;
    bb.bb_target = location.target;
    bb.bb_channel = location.channel;
    rv = ioctl(devh, BIOCBLINK, &bb);

    if (rv == 0 && bb.bb_bio.bio_status.bs_status == BIO_STATUS_UNKNOWN)
        return;

    if (rv == 0 && bb.bb_bio.bio_status.bs_status == BIO_STATUS_SUCCESS) {
        bio_status(&bb.bb_bio.bio_status);
        return;
    }

    /* if the blink didn't work, try to find something that will */

    memset(&bi, 0, sizeof(bi));
    bi.bi_bio.bio_cookie = bio_cookie;
    if (ioctl(devh, BIOCINQ, &bi))
        err(1, "BIOCINQ");

    bio_status(&bi.bi_bio.bio_status);

    for (v = 0; v < bi.bi_novol; v++) {
        memset(&bv, 0, sizeof(bv));
        bv.bv_bio.bio_cookie = bio_cookie;
        bv.bv_volid = v;
        if (ioctl(devh, BIOCVOL, &bv))
            err(1, "BIOCVOL");

        bio_status(&bv.bv_bio.bio_status);

        if (name && strcmp(name, bv.bv_dev) != 0)
            continue;

        for (d = 0; d < bv.bv_nodisk; d++) {
            memset(&bd, 0, sizeof(bd));
            bd.bd_bio.bio_cookie = bio_cookie;
            bd.bd_volid = v;
            bd.bd_diskid = d;

            if (ioctl(devh, BIOCDISK, &bd))
                err(1, "BIOCDISK");

            bio_status(&bd.bd_bio.bio_status);

            if (bd.bd_channel == location.channel &&
                    bd.bd_target == location.target &&
                    bd.bd_lun == location.lun) {
                if (bd.bd_procdev[0] != '\0')
                    bio_blink(bd.bd_procdev,
                              location.target, blink);
                else
                    warnx("Disk %s is not in an enclosure",
                          arg);
                return;
            }
        }
    }

    warnx("Disk %s does not exist", arg);

    return;
}
Example #12
0
void
bio_inq(char *name)
{
    char 			*status, *cache;
    char			size[64], scsiname[16], volname[32];
    char			percent[10], seconds[20];
    int			i, d, volheader, hotspare, unused;
    char			encname[16], serial[32];
    struct bioc_inq		bi;
    struct bioc_vol		bv;
    struct bioc_disk	bd;

    memset(&bi, 0, sizeof(bi));

    bi.bi_bio.bio_cookie = bio_cookie;

    if (ioctl(devh, BIOCINQ, &bi)) {
        if (errno == ENOTTY)
            bio_diskinq(name);
        else
            err(1, "BIOCINQ");
        return;
    }

    bio_status(&bi.bi_bio.bio_status);

    volheader = 0;
    for (i = 0; i < bi.bi_novol; i++) {
        memset(&bv, 0, sizeof(bv));
        bv.bv_bio.bio_cookie = bio_cookie;
        bv.bv_volid = i;
        bv.bv_percent = -1;
        bv.bv_seconds = 0;

        if (ioctl(devh, BIOCVOL, &bv))
            err(1, "BIOCVOL");

        bio_status(&bv.bv_bio.bio_status);

        if (name && strcmp(name, bv.bv_dev) != 0)
            continue;

        if (!volheader) {
            volheader = 1;
            printf("%-11s %-10s %14s %-8s\n",
                   "Volume", "Status", "Size", "Device");
        }

        percent[0] = '\0';
        seconds[0] = '\0';
        if (bv.bv_percent != -1)
            snprintf(percent, sizeof percent,
                     " %d%% done", bv.bv_percent);
        if (bv.bv_seconds)
            snprintf(seconds, sizeof seconds,
                     " %u seconds", bv.bv_seconds);
        switch (bv.bv_status) {
        case BIOC_SVONLINE:
            status = BIOC_SVONLINE_S;
            break;
        case BIOC_SVOFFLINE:
            status = BIOC_SVOFFLINE_S;
            break;
        case BIOC_SVDEGRADED:
            status = BIOC_SVDEGRADED_S;
            break;
        case BIOC_SVBUILDING:
            status = BIOC_SVBUILDING_S;
            break;
        case BIOC_SVREBUILD:
            status = BIOC_SVREBUILD_S;
            break;
        case BIOC_SVSCRUB:
            status = BIOC_SVSCRUB_S;
            break;
        case BIOC_SVINVALID:
        default:
            status = BIOC_SVINVALID_S;
        }
        switch (bv.bv_cache) {
        case BIOC_CVWRITEBACK:
            cache = BIOC_CVWRITEBACK_S;
            break;
        case BIOC_CVWRITETHROUGH:
            cache = BIOC_CVWRITETHROUGH_S;
            break;
        case BIOC_CVUNKNOWN:
        default:
            cache = BIOC_CVUNKNOWN_S;
        }

        snprintf(volname, sizeof volname, "%s %u",
                 bi.bi_dev, bv.bv_volid);

        unused = 0;
        hotspare = 0;
        if (bv.bv_level == -1 && bv.bv_nodisk == 1)
            hotspare = 1;
        else if (bv.bv_level == -2 && bv.bv_nodisk == 1)
            unused = 1;
        else {
            if (human)
                fmt_scaled(bv.bv_size, size);
            else
                snprintf(size, sizeof size, "%14llu",
                         bv.bv_size);
            switch (bv.bv_level) {
            case 'C':
                printf("%11s %-10s %14s %-7s CRYPTO%s%s\n",
                       volname, status, size, bv.bv_dev,
                       percent, seconds);
                break;
            case 'c':
                printf("%11s %-10s %14s %-7s CONCAT%s%s\n",
                       volname, status, size, bv.bv_dev,
                       percent, seconds);
                break;
            default:
                printf("%11s %-10s %14s %-7s RAID%u%s%s %s\n",
                       volname, status, size, bv.bv_dev,
                       bv.bv_level, percent, seconds, cache);
                break;
            }

        }

        for (d = 0; d < bv.bv_nodisk; d++) {
            memset(&bd, 0, sizeof(bd));
            bd.bd_bio.bio_cookie = bio_cookie;
            bd.bd_diskid = d;
            bd.bd_volid = i;

            if (ioctl(devh, BIOCDISK, &bd))
                err(1, "BIOCDISK");

            bio_status(&bd.bd_bio.bio_status);

            switch (bd.bd_status) {
            case BIOC_SDONLINE:
                status = BIOC_SDONLINE_S;
                break;
            case BIOC_SDOFFLINE:
                status = BIOC_SDOFFLINE_S;
                break;
            case BIOC_SDFAILED:
                status = BIOC_SDFAILED_S;
                break;
            case BIOC_SDREBUILD:
                status = BIOC_SDREBUILD_S;
                break;
            case BIOC_SDHOTSPARE:
                status = BIOC_SDHOTSPARE_S;
                break;
            case BIOC_SDUNUSED:
                status = BIOC_SDUNUSED_S;
                break;
            case BIOC_SDSCRUB:
                status = BIOC_SDSCRUB_S;
                break;
            case BIOC_SDINVALID:
            default:
                status = BIOC_SDINVALID_S;
            }

            if (hotspare || unused)
                ;	/* use volname from parent volume */
            else
                snprintf(volname, sizeof volname, "    %3u",
                         bd.bd_diskid);

            if (bv.bv_level == 'C' && bd.bd_size == 0)
                snprintf(size, sizeof size, "%14s", "key disk");
            else if (human)
                fmt_scaled(bd.bd_size, size);
            else
                snprintf(size, sizeof size, "%14llu",
                         bd.bd_size);
            snprintf(scsiname, sizeof scsiname,
                     "%u:%u.%u",
                     bd.bd_channel, bd.bd_target, bd.bd_lun);
            if (bd.bd_procdev[0])
                strlcpy(encname, bd.bd_procdev, sizeof encname);
            else
                strlcpy(encname, "noencl", sizeof encname);
            if (bd.bd_serial[0])
                strlcpy(serial, bd.bd_serial, sizeof serial);
            else
                strlcpy(serial, "unknown serial", sizeof serial);

            printf("%11s %-10s %14s %-7s %-6s <%s>\n",
                   volname, status, size, scsiname, encname,
                   bd.bd_vendor);
            if (verbose)
                printf("%11s %-10s %14s %-7s %-6s '%s'\n",
                       "", "", "", "", "", serial);
        }
    }
}