14914ee11SToomas Soome /*- 24914ee11SToomas Soome * Copyright 2019 Toomas Soome <tsoome@me.com> 34914ee11SToomas Soome * 44914ee11SToomas Soome * Redistribution and use in source and binary forms, with or without 54914ee11SToomas Soome * modification, are permitted provided that the following conditions 64914ee11SToomas Soome * are met: 74914ee11SToomas Soome * 1. Redistributions of source code must retain the above copyright 84914ee11SToomas Soome * notice, this list of conditions and the following disclaimer. 94914ee11SToomas Soome * 2. Redistributions in binary form must reproduce the above copyright 104914ee11SToomas Soome * notice, this list of conditions and the following disclaimer in the 114914ee11SToomas Soome * documentation and/or other materials provided with the distribution. 124914ee11SToomas Soome * 134914ee11SToomas Soome * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 144914ee11SToomas Soome * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 154914ee11SToomas Soome * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 164914ee11SToomas Soome * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 174914ee11SToomas Soome * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 184914ee11SToomas Soome * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 194914ee11SToomas Soome * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 204914ee11SToomas Soome * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 214914ee11SToomas Soome * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 224914ee11SToomas Soome * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 234914ee11SToomas Soome * SUCH DAMAGE. 244914ee11SToomas Soome */ 254914ee11SToomas Soome 264914ee11SToomas Soome #include <sys/cdefs.h> 274914ee11SToomas Soome __FBSDID("$FreeBSD$"); 284914ee11SToomas Soome 294914ee11SToomas Soome #include <stand.h> 304914ee11SToomas Soome #include <stdarg.h> 314914ee11SToomas Soome #include <machine/_inttypes.h> 324914ee11SToomas Soome #include <bootstrap.h> 334914ee11SToomas Soome #include <sys/disk.h> 344914ee11SToomas Soome #include <sys/errno.h> 354914ee11SToomas Soome #include <sys/queue.h> 364914ee11SToomas Soome #include <sys/param.h> 374914ee11SToomas Soome #include <disk.h> 384914ee11SToomas Soome 394914ee11SToomas Soome static int vdisk_init(void); 404914ee11SToomas Soome static int vdisk_strategy(void *, int, daddr_t, size_t, char *, size_t *); 414914ee11SToomas Soome static int vdisk_open(struct open_file *, ...); 424914ee11SToomas Soome static int vdisk_close(struct open_file *); 434914ee11SToomas Soome static int vdisk_ioctl(struct open_file *, u_long, void *); 444914ee11SToomas Soome static int vdisk_print(int); 454914ee11SToomas Soome 464914ee11SToomas Soome struct devsw vdisk_dev = { 474914ee11SToomas Soome .dv_name = "vdisk", 484914ee11SToomas Soome .dv_type = DEVT_DISK, 494914ee11SToomas Soome .dv_init = vdisk_init, 504914ee11SToomas Soome .dv_strategy = vdisk_strategy, 514914ee11SToomas Soome .dv_open = vdisk_open, 524914ee11SToomas Soome .dv_close = vdisk_close, 534914ee11SToomas Soome .dv_ioctl = vdisk_ioctl, 544914ee11SToomas Soome .dv_print = vdisk_print, 554914ee11SToomas Soome .dv_cleanup = NULL 564914ee11SToomas Soome }; 574914ee11SToomas Soome 584914ee11SToomas Soome typedef STAILQ_HEAD(vdisk_info_list, vdisk_info) vdisk_info_list_t; 594914ee11SToomas Soome 604914ee11SToomas Soome typedef struct vdisk_info 614914ee11SToomas Soome { 624914ee11SToomas Soome STAILQ_ENTRY(vdisk_info) vdisk_link; /* link in device list */ 634914ee11SToomas Soome char *vdisk_path; 644914ee11SToomas Soome int vdisk_unit; 654914ee11SToomas Soome int vdisk_fd; 664914ee11SToomas Soome uint64_t vdisk_size; /* size in bytes */ 674914ee11SToomas Soome uint32_t vdisk_sectorsz; 684914ee11SToomas Soome uint32_t vdisk_open; /* reference counter */ 694914ee11SToomas Soome } vdisk_info_t; 704914ee11SToomas Soome 714914ee11SToomas Soome static vdisk_info_list_t vdisk_list; /* list of mapped vdisks. */ 724914ee11SToomas Soome 734914ee11SToomas Soome static vdisk_info_t * 744914ee11SToomas Soome vdisk_get_info(struct devdesc *dev) 754914ee11SToomas Soome { 764914ee11SToomas Soome vdisk_info_t *vd; 774914ee11SToomas Soome 784914ee11SToomas Soome STAILQ_FOREACH(vd, &vdisk_list, vdisk_link) { 794914ee11SToomas Soome if (vd->vdisk_unit == dev->d_unit) 804914ee11SToomas Soome return (vd); 814914ee11SToomas Soome } 824914ee11SToomas Soome return (vd); 834914ee11SToomas Soome } 844914ee11SToomas Soome 854914ee11SToomas Soome COMMAND_SET(map_vdisk, "map-vdisk", "map file as virtual disk", command_mapvd); 864914ee11SToomas Soome 874914ee11SToomas Soome static int 884914ee11SToomas Soome command_mapvd(int argc, char *argv[]) 894914ee11SToomas Soome { 904914ee11SToomas Soome vdisk_info_t *vd, *p; 914914ee11SToomas Soome struct stat sb; 924914ee11SToomas Soome 934914ee11SToomas Soome if (argc != 2) { 944914ee11SToomas Soome printf("usage: %s filename\n", argv[0]); 954914ee11SToomas Soome return (CMD_ERROR); 964914ee11SToomas Soome } 974914ee11SToomas Soome 984914ee11SToomas Soome STAILQ_FOREACH(vd, &vdisk_list, vdisk_link) { 994914ee11SToomas Soome if (strcmp(vd->vdisk_path, argv[1]) == 0) { 1004914ee11SToomas Soome printf("%s: file %s is already mapped as %s%d\n", 1014914ee11SToomas Soome argv[0], argv[1], vdisk_dev.dv_name, 1024914ee11SToomas Soome vd->vdisk_unit); 1034914ee11SToomas Soome return (CMD_ERROR); 1044914ee11SToomas Soome } 1054914ee11SToomas Soome } 1064914ee11SToomas Soome 1074914ee11SToomas Soome if (stat(argv[1], &sb) < 0) { 1084914ee11SToomas Soome /* 1094914ee11SToomas Soome * ENOSYS is really ENOENT because we did try to walk 1104914ee11SToomas Soome * through devsw list to try to open this file. 1114914ee11SToomas Soome */ 1124914ee11SToomas Soome if (errno == ENOSYS) 1134914ee11SToomas Soome errno = ENOENT; 1144914ee11SToomas Soome 1154914ee11SToomas Soome printf("%s: stat failed: %s\n", argv[0], strerror(errno)); 1164914ee11SToomas Soome return (CMD_ERROR); 1174914ee11SToomas Soome } 1184914ee11SToomas Soome 1194914ee11SToomas Soome /* 1204914ee11SToomas Soome * Avoid mapping small files. 1214914ee11SToomas Soome */ 1224914ee11SToomas Soome if (sb.st_size < 1024 * 1024) { 1234914ee11SToomas Soome printf("%s: file %s is too small.\n", argv[0], argv[1]); 1244914ee11SToomas Soome return (CMD_ERROR); 1254914ee11SToomas Soome } 1264914ee11SToomas Soome 1274914ee11SToomas Soome vd = calloc(1, sizeof (*vd)); 1284914ee11SToomas Soome if (vd == NULL) { 1294914ee11SToomas Soome printf("%s: out of memory\n", argv[0]); 1304914ee11SToomas Soome return (CMD_ERROR); 1314914ee11SToomas Soome } 1324914ee11SToomas Soome vd->vdisk_path = strdup(argv[1]); 1334914ee11SToomas Soome if (vd->vdisk_path == NULL) { 1344914ee11SToomas Soome free (vd); 1354914ee11SToomas Soome printf("%s: out of memory\n", argv[0]); 1364914ee11SToomas Soome return (CMD_ERROR); 1374914ee11SToomas Soome } 1384914ee11SToomas Soome vd->vdisk_fd = open(vd->vdisk_path, O_RDONLY); 1394914ee11SToomas Soome if (vd->vdisk_fd < 0) { 1404914ee11SToomas Soome printf("%s: open failed: %s\n", argv[0], strerror(errno)); 1414914ee11SToomas Soome free(vd->vdisk_path); 1424914ee11SToomas Soome free(vd); 1434914ee11SToomas Soome return (CMD_ERROR); 1444914ee11SToomas Soome } 1454914ee11SToomas Soome 1464914ee11SToomas Soome vd->vdisk_size = sb.st_size; 1474914ee11SToomas Soome vd->vdisk_sectorsz = DEV_BSIZE; 1484914ee11SToomas Soome STAILQ_FOREACH(p, &vdisk_list, vdisk_link) { 1494914ee11SToomas Soome vdisk_info_t *n; 1504914ee11SToomas Soome if (p->vdisk_unit == vd->vdisk_unit) { 1514914ee11SToomas Soome vd->vdisk_unit++; 1524914ee11SToomas Soome continue; 1534914ee11SToomas Soome } 1544914ee11SToomas Soome n = STAILQ_NEXT(p, vdisk_link); 1554914ee11SToomas Soome if (p->vdisk_unit < vd->vdisk_unit) { 1564914ee11SToomas Soome if (n == NULL) { 1574914ee11SToomas Soome /* p is last elem */ 1584914ee11SToomas Soome STAILQ_INSERT_TAIL(&vdisk_list, vd, vdisk_link); 1594914ee11SToomas Soome break; 1604914ee11SToomas Soome } 1614914ee11SToomas Soome if (n->vdisk_unit > vd->vdisk_unit) { 1624914ee11SToomas Soome /* p < vd < n */ 1634914ee11SToomas Soome STAILQ_INSERT_AFTER(&vdisk_list, p, vd, 1644914ee11SToomas Soome vdisk_link); 1654914ee11SToomas Soome break; 1664914ee11SToomas Soome } 1674914ee11SToomas Soome /* else n < vd or n == vd */ 1684914ee11SToomas Soome vd->vdisk_unit++; 1694914ee11SToomas Soome continue; 1704914ee11SToomas Soome } 1714914ee11SToomas Soome /* p > vd only if p is the first element */ 1724914ee11SToomas Soome STAILQ_INSERT_HEAD(&vdisk_list, vd, vdisk_link); 1734914ee11SToomas Soome break; 1744914ee11SToomas Soome } 1754914ee11SToomas Soome 1764914ee11SToomas Soome /* if the list was empty or contiguous */ 1774914ee11SToomas Soome if (p == NULL) 1784914ee11SToomas Soome STAILQ_INSERT_TAIL(&vdisk_list, vd, vdisk_link); 1794914ee11SToomas Soome 1804914ee11SToomas Soome printf("%s: file %s is mapped as %s%d\n", argv[0], vd->vdisk_path, 1814914ee11SToomas Soome vdisk_dev.dv_name, vd->vdisk_unit); 1824914ee11SToomas Soome return (CMD_OK); 1834914ee11SToomas Soome } 1844914ee11SToomas Soome 1854914ee11SToomas Soome COMMAND_SET(unmap_vdisk, "unmap-vdisk", "unmap virtual disk", command_unmapvd); 1864914ee11SToomas Soome 1874914ee11SToomas Soome /* 1884914ee11SToomas Soome * unmap-vdisk vdiskX 1894914ee11SToomas Soome */ 1904914ee11SToomas Soome static int 1914914ee11SToomas Soome command_unmapvd(int argc, char *argv[]) 1924914ee11SToomas Soome { 1934914ee11SToomas Soome size_t len; 1944914ee11SToomas Soome vdisk_info_t *vd; 1954914ee11SToomas Soome long unit; 1964914ee11SToomas Soome char *end; 1974914ee11SToomas Soome 1984914ee11SToomas Soome if (argc != 2) { 1994914ee11SToomas Soome printf("usage: %s %sN\n", argv[0], vdisk_dev.dv_name); 2004914ee11SToomas Soome return (CMD_ERROR); 2014914ee11SToomas Soome } 2024914ee11SToomas Soome 2034914ee11SToomas Soome len = strlen(vdisk_dev.dv_name); 2044914ee11SToomas Soome if (strncmp(vdisk_dev.dv_name, argv[1], len) != 0) { 2054914ee11SToomas Soome printf("%s: unknown device %s\n", argv[0], argv[1]); 2064914ee11SToomas Soome return (CMD_ERROR); 2074914ee11SToomas Soome } 2084914ee11SToomas Soome errno = 0; 2094914ee11SToomas Soome unit = strtol(argv[1] + len, &end, 10); 2104914ee11SToomas Soome if (errno != 0 || (*end != '\0' && strcmp(end, ":") != 0)) { 2114914ee11SToomas Soome printf("%s: unknown device %s\n", argv[0], argv[1]); 2124914ee11SToomas Soome return (CMD_ERROR); 2134914ee11SToomas Soome } 2144914ee11SToomas Soome 2154914ee11SToomas Soome STAILQ_FOREACH(vd, &vdisk_list, vdisk_link) { 2164914ee11SToomas Soome if (vd->vdisk_unit == unit) 2174914ee11SToomas Soome break; 2184914ee11SToomas Soome } 2194914ee11SToomas Soome 2204914ee11SToomas Soome if (vd == NULL) { 2214914ee11SToomas Soome printf("%s: unknown device %s\n", argv[0], argv[1]); 2224914ee11SToomas Soome return (CMD_ERROR); 2234914ee11SToomas Soome } 2244914ee11SToomas Soome 2254914ee11SToomas Soome if (vd->vdisk_open != 0) { 2264914ee11SToomas Soome printf("%s: %s is in use, unable to unmap.\n", 2274914ee11SToomas Soome argv[0], argv[1]); 2284914ee11SToomas Soome return (CMD_ERROR); 2294914ee11SToomas Soome } 2304914ee11SToomas Soome 2314914ee11SToomas Soome STAILQ_REMOVE(&vdisk_list, vd, vdisk_info, vdisk_link); 232*68031519SToomas Soome (void) close(vd->vdisk_fd); 233*68031519SToomas Soome printf("%s (%s) unmapped\n", argv[1], vd->vdisk_path); 2344914ee11SToomas Soome free(vd->vdisk_path); 2354914ee11SToomas Soome free(vd); 2364914ee11SToomas Soome 2374914ee11SToomas Soome return (CMD_OK); 2384914ee11SToomas Soome } 2394914ee11SToomas Soome 2404914ee11SToomas Soome static int 2414914ee11SToomas Soome vdisk_init(void) 2424914ee11SToomas Soome { 2434914ee11SToomas Soome STAILQ_INIT(&vdisk_list); 2444914ee11SToomas Soome return (0); 2454914ee11SToomas Soome } 2464914ee11SToomas Soome 2474914ee11SToomas Soome static int 2484914ee11SToomas Soome vdisk_strategy(void *devdata, int rw, daddr_t blk, size_t size, 2494914ee11SToomas Soome char *buf, size_t *rsize) 2504914ee11SToomas Soome { 2514914ee11SToomas Soome struct disk_devdesc *dev; 2524914ee11SToomas Soome vdisk_info_t *vd; 2534914ee11SToomas Soome ssize_t rv; 2544914ee11SToomas Soome 2554914ee11SToomas Soome dev = devdata; 2564914ee11SToomas Soome if (dev == NULL) 2574914ee11SToomas Soome return (EINVAL); 2584914ee11SToomas Soome vd = vdisk_get_info((struct devdesc *)dev); 2594914ee11SToomas Soome if (vd == NULL) 2604914ee11SToomas Soome return (EINVAL); 2614914ee11SToomas Soome 2624914ee11SToomas Soome if (size == 0 || (size % 512) != 0) 2634914ee11SToomas Soome return (EIO); 2644914ee11SToomas Soome 2654914ee11SToomas Soome if (dev->dd.d_dev->dv_type == DEVT_DISK) { 2664914ee11SToomas Soome daddr_t offset; 2674914ee11SToomas Soome 2684914ee11SToomas Soome offset = dev->d_offset * vd->vdisk_sectorsz; 2694914ee11SToomas Soome offset /= 512; 2704914ee11SToomas Soome blk += offset; 2714914ee11SToomas Soome } 2724914ee11SToomas Soome if (lseek(vd->vdisk_fd, blk << 9, SEEK_SET) == -1) 2734914ee11SToomas Soome return (EIO); 2744914ee11SToomas Soome 2754914ee11SToomas Soome errno = 0; 2764914ee11SToomas Soome switch (rw & F_MASK) { 2774914ee11SToomas Soome case F_READ: 2784914ee11SToomas Soome rv = read(vd->vdisk_fd, buf, size); 2794914ee11SToomas Soome break; 2804914ee11SToomas Soome case F_WRITE: 2814914ee11SToomas Soome rv = write(vd->vdisk_fd, buf, size); 2824914ee11SToomas Soome break; 2834914ee11SToomas Soome default: 2844914ee11SToomas Soome return (ENOSYS); 2854914ee11SToomas Soome } 2864914ee11SToomas Soome 2874914ee11SToomas Soome if (errno == 0 && rsize != NULL) { 2884914ee11SToomas Soome *rsize = rv; 2894914ee11SToomas Soome } 2904914ee11SToomas Soome return (errno); 2914914ee11SToomas Soome } 2924914ee11SToomas Soome 2934914ee11SToomas Soome static int 2944914ee11SToomas Soome vdisk_open(struct open_file *f, ...) 2954914ee11SToomas Soome { 2964914ee11SToomas Soome va_list args; 2974914ee11SToomas Soome struct disk_devdesc *dev; 2984914ee11SToomas Soome vdisk_info_t *vd; 2994914ee11SToomas Soome int rc = 0; 3004914ee11SToomas Soome 3014914ee11SToomas Soome va_start(args, f); 3024914ee11SToomas Soome dev = va_arg(args, struct disk_devdesc *); 3034914ee11SToomas Soome va_end(args); 3044914ee11SToomas Soome if (dev == NULL) 3054914ee11SToomas Soome return (EINVAL); 3064914ee11SToomas Soome vd = vdisk_get_info((struct devdesc *)dev); 3074914ee11SToomas Soome if (vd == NULL) 3084914ee11SToomas Soome return (EINVAL); 3094914ee11SToomas Soome 3104914ee11SToomas Soome if (dev->dd.d_dev->dv_type == DEVT_DISK) { 3114914ee11SToomas Soome rc = disk_open(dev, vd->vdisk_size, vd->vdisk_sectorsz); 3124914ee11SToomas Soome } 3134914ee11SToomas Soome if (rc == 0) 3144914ee11SToomas Soome vd->vdisk_open++; 3154914ee11SToomas Soome return (rc); 3164914ee11SToomas Soome } 3174914ee11SToomas Soome 3184914ee11SToomas Soome static int 3194914ee11SToomas Soome vdisk_close(struct open_file *f) 3204914ee11SToomas Soome { 3214914ee11SToomas Soome struct disk_devdesc *dev; 3224914ee11SToomas Soome vdisk_info_t *vd; 3234914ee11SToomas Soome 3244914ee11SToomas Soome dev = (struct disk_devdesc *)(f->f_devdata); 3254914ee11SToomas Soome if (dev == NULL) 3264914ee11SToomas Soome return (EINVAL); 3274914ee11SToomas Soome vd = vdisk_get_info((struct devdesc *)dev); 3284914ee11SToomas Soome if (vd == NULL) 3294914ee11SToomas Soome return (EINVAL); 3304914ee11SToomas Soome 3314914ee11SToomas Soome vd->vdisk_open--; 3324914ee11SToomas Soome if (dev->dd.d_dev->dv_type == DEVT_DISK) 3334914ee11SToomas Soome return (disk_close(dev)); 3344914ee11SToomas Soome return (0); 3354914ee11SToomas Soome } 3364914ee11SToomas Soome 3374914ee11SToomas Soome static int 3384914ee11SToomas Soome vdisk_ioctl(struct open_file *f, u_long cmd, void *data) 3394914ee11SToomas Soome { 3404914ee11SToomas Soome struct disk_devdesc *dev; 3414914ee11SToomas Soome vdisk_info_t *vd; 3424914ee11SToomas Soome int rc; 3434914ee11SToomas Soome 3444914ee11SToomas Soome dev = (struct disk_devdesc *)(f->f_devdata); 3454914ee11SToomas Soome if (dev == NULL) 3464914ee11SToomas Soome return (EINVAL); 3474914ee11SToomas Soome vd = vdisk_get_info((struct devdesc *)dev); 3484914ee11SToomas Soome if (vd == NULL) 3494914ee11SToomas Soome return (EINVAL); 3504914ee11SToomas Soome 3514914ee11SToomas Soome if (dev->dd.d_dev->dv_type == DEVT_DISK) { 3524914ee11SToomas Soome rc = disk_ioctl(dev, cmd, data); 3534914ee11SToomas Soome if (rc != ENOTTY) 3544914ee11SToomas Soome return (rc); 3554914ee11SToomas Soome } 3564914ee11SToomas Soome 3574914ee11SToomas Soome switch (cmd) { 3584914ee11SToomas Soome case DIOCGSECTORSIZE: 3594914ee11SToomas Soome *(u_int *)data = vd->vdisk_sectorsz; 3604914ee11SToomas Soome break; 3614914ee11SToomas Soome case DIOCGMEDIASIZE: 3624914ee11SToomas Soome *(uint64_t *)data = vd->vdisk_size; 3634914ee11SToomas Soome break; 3644914ee11SToomas Soome default: 3654914ee11SToomas Soome return (ENOTTY); 3664914ee11SToomas Soome } 3674914ee11SToomas Soome return (0); 3684914ee11SToomas Soome } 3694914ee11SToomas Soome 3704914ee11SToomas Soome static int 3714914ee11SToomas Soome vdisk_print(int verbose) 3724914ee11SToomas Soome { 3734914ee11SToomas Soome int ret = 0; 3744914ee11SToomas Soome vdisk_info_t *vd; 3754914ee11SToomas Soome char line[80]; 3764914ee11SToomas Soome 3774914ee11SToomas Soome if (STAILQ_EMPTY(&vdisk_list)) 3784914ee11SToomas Soome return (ret); 3794914ee11SToomas Soome 3804914ee11SToomas Soome printf("%s devices:", vdisk_dev.dv_name); 3814914ee11SToomas Soome if ((ret = pager_output("\n")) != 0) 3824914ee11SToomas Soome return (ret); 3834914ee11SToomas Soome 3844914ee11SToomas Soome STAILQ_FOREACH(vd, &vdisk_list, vdisk_link) { 3854914ee11SToomas Soome struct disk_devdesc vd_dev; 3864914ee11SToomas Soome 3874914ee11SToomas Soome if (verbose) { 3884914ee11SToomas Soome printf(" %s", vd->vdisk_path); 3894914ee11SToomas Soome if ((ret = pager_output("\n")) != 0) 3904914ee11SToomas Soome break; 3914914ee11SToomas Soome } 3924914ee11SToomas Soome snprintf(line, sizeof(line), 3934914ee11SToomas Soome " %s%d", vdisk_dev.dv_name, vd->vdisk_unit); 3944914ee11SToomas Soome printf("%s: %" PRIu64 " X %u blocks", line, 3954914ee11SToomas Soome vd->vdisk_size / vd->vdisk_sectorsz, 3964914ee11SToomas Soome vd->vdisk_sectorsz); 3974914ee11SToomas Soome if ((ret = pager_output("\n")) != 0) 3984914ee11SToomas Soome break; 3994914ee11SToomas Soome 4004914ee11SToomas Soome vd_dev.dd.d_dev = &vdisk_dev; 4014914ee11SToomas Soome vd_dev.dd.d_unit = vd->vdisk_unit; 4024914ee11SToomas Soome vd_dev.d_slice = -1; 4034914ee11SToomas Soome vd_dev.d_partition = -1; 4044914ee11SToomas Soome 4054914ee11SToomas Soome ret = disk_open(&vd_dev, vd->vdisk_size, vd->vdisk_sectorsz); 4064914ee11SToomas Soome if (ret == 0) { 4074914ee11SToomas Soome ret = disk_print(&vd_dev, line, verbose); 4084914ee11SToomas Soome disk_close(&vd_dev); 4094914ee11SToomas Soome if (ret != 0) 4104914ee11SToomas Soome break; 4114914ee11SToomas Soome } else { 4124914ee11SToomas Soome ret = 0; 4134914ee11SToomas Soome } 4144914ee11SToomas Soome } 4154914ee11SToomas Soome 4164914ee11SToomas Soome return (ret); 4174914ee11SToomas Soome } 418