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, 55e98f952cSWarner Losh .dv_cleanup = nullsys, 56*ad759c73SWarner Losh .dv_fmtdev = disk_fmtdev, 574914ee11SToomas Soome }; 584914ee11SToomas Soome 594914ee11SToomas Soome typedef STAILQ_HEAD(vdisk_info_list, vdisk_info) vdisk_info_list_t; 604914ee11SToomas Soome 614914ee11SToomas Soome typedef struct vdisk_info 624914ee11SToomas Soome { 634914ee11SToomas Soome STAILQ_ENTRY(vdisk_info) vdisk_link; /* link in device list */ 644914ee11SToomas Soome char *vdisk_path; 654914ee11SToomas Soome int vdisk_unit; 664914ee11SToomas Soome int vdisk_fd; 674914ee11SToomas Soome uint64_t vdisk_size; /* size in bytes */ 684914ee11SToomas Soome uint32_t vdisk_sectorsz; 694914ee11SToomas Soome uint32_t vdisk_open; /* reference counter */ 704914ee11SToomas Soome } vdisk_info_t; 714914ee11SToomas Soome 724914ee11SToomas Soome static vdisk_info_list_t vdisk_list; /* list of mapped vdisks. */ 734914ee11SToomas Soome 744914ee11SToomas Soome static vdisk_info_t * 754914ee11SToomas Soome vdisk_get_info(struct devdesc *dev) 764914ee11SToomas Soome { 774914ee11SToomas Soome vdisk_info_t *vd; 784914ee11SToomas Soome 794914ee11SToomas Soome STAILQ_FOREACH(vd, &vdisk_list, vdisk_link) { 804914ee11SToomas Soome if (vd->vdisk_unit == dev->d_unit) 814914ee11SToomas Soome return (vd); 824914ee11SToomas Soome } 834914ee11SToomas Soome return (vd); 844914ee11SToomas Soome } 854914ee11SToomas Soome 864914ee11SToomas Soome COMMAND_SET(map_vdisk, "map-vdisk", "map file as virtual disk", command_mapvd); 874914ee11SToomas Soome 884914ee11SToomas Soome static int 894914ee11SToomas Soome command_mapvd(int argc, char *argv[]) 904914ee11SToomas Soome { 914914ee11SToomas Soome vdisk_info_t *vd, *p; 924914ee11SToomas Soome struct stat sb; 934914ee11SToomas Soome 944914ee11SToomas Soome if (argc != 2) { 954914ee11SToomas Soome printf("usage: %s filename\n", argv[0]); 964914ee11SToomas Soome return (CMD_ERROR); 974914ee11SToomas Soome } 984914ee11SToomas Soome 994914ee11SToomas Soome STAILQ_FOREACH(vd, &vdisk_list, vdisk_link) { 1004914ee11SToomas Soome if (strcmp(vd->vdisk_path, argv[1]) == 0) { 1014914ee11SToomas Soome printf("%s: file %s is already mapped as %s%d\n", 1024914ee11SToomas Soome argv[0], argv[1], vdisk_dev.dv_name, 1034914ee11SToomas Soome vd->vdisk_unit); 1044914ee11SToomas Soome return (CMD_ERROR); 1054914ee11SToomas Soome } 1064914ee11SToomas Soome } 1074914ee11SToomas Soome 1084914ee11SToomas Soome if (stat(argv[1], &sb) < 0) { 1094914ee11SToomas Soome /* 1104914ee11SToomas Soome * ENOSYS is really ENOENT because we did try to walk 1114914ee11SToomas Soome * through devsw list to try to open this file. 1124914ee11SToomas Soome */ 1134914ee11SToomas Soome if (errno == ENOSYS) 1144914ee11SToomas Soome errno = ENOENT; 1154914ee11SToomas Soome 1164914ee11SToomas Soome printf("%s: stat failed: %s\n", argv[0], strerror(errno)); 1174914ee11SToomas Soome return (CMD_ERROR); 1184914ee11SToomas Soome } 1194914ee11SToomas Soome 1204914ee11SToomas Soome /* 1214914ee11SToomas Soome * Avoid mapping small files. 1224914ee11SToomas Soome */ 1234914ee11SToomas Soome if (sb.st_size < 1024 * 1024) { 1244914ee11SToomas Soome printf("%s: file %s is too small.\n", argv[0], argv[1]); 1254914ee11SToomas Soome return (CMD_ERROR); 1264914ee11SToomas Soome } 1274914ee11SToomas Soome 1284914ee11SToomas Soome vd = calloc(1, sizeof (*vd)); 1294914ee11SToomas Soome if (vd == NULL) { 1304914ee11SToomas Soome printf("%s: out of memory\n", argv[0]); 1314914ee11SToomas Soome return (CMD_ERROR); 1324914ee11SToomas Soome } 1334914ee11SToomas Soome vd->vdisk_path = strdup(argv[1]); 1344914ee11SToomas Soome if (vd->vdisk_path == NULL) { 1354914ee11SToomas Soome free (vd); 1364914ee11SToomas Soome printf("%s: out of memory\n", argv[0]); 1374914ee11SToomas Soome return (CMD_ERROR); 1384914ee11SToomas Soome } 1394914ee11SToomas Soome vd->vdisk_fd = open(vd->vdisk_path, O_RDONLY); 1404914ee11SToomas Soome if (vd->vdisk_fd < 0) { 1414914ee11SToomas Soome printf("%s: open failed: %s\n", argv[0], strerror(errno)); 1424914ee11SToomas Soome free(vd->vdisk_path); 1434914ee11SToomas Soome free(vd); 1444914ee11SToomas Soome return (CMD_ERROR); 1454914ee11SToomas Soome } 1464914ee11SToomas Soome 1474914ee11SToomas Soome vd->vdisk_size = sb.st_size; 1484914ee11SToomas Soome vd->vdisk_sectorsz = DEV_BSIZE; 1494914ee11SToomas Soome STAILQ_FOREACH(p, &vdisk_list, vdisk_link) { 1504914ee11SToomas Soome vdisk_info_t *n; 1514914ee11SToomas Soome if (p->vdisk_unit == vd->vdisk_unit) { 1524914ee11SToomas Soome vd->vdisk_unit++; 1534914ee11SToomas Soome continue; 1544914ee11SToomas Soome } 1554914ee11SToomas Soome n = STAILQ_NEXT(p, vdisk_link); 1564914ee11SToomas Soome if (p->vdisk_unit < vd->vdisk_unit) { 1574914ee11SToomas Soome if (n == NULL) { 1584914ee11SToomas Soome /* p is last elem */ 1594914ee11SToomas Soome STAILQ_INSERT_TAIL(&vdisk_list, vd, vdisk_link); 1604914ee11SToomas Soome break; 1614914ee11SToomas Soome } 1624914ee11SToomas Soome if (n->vdisk_unit > vd->vdisk_unit) { 1634914ee11SToomas Soome /* p < vd < n */ 1644914ee11SToomas Soome STAILQ_INSERT_AFTER(&vdisk_list, p, vd, 1654914ee11SToomas Soome vdisk_link); 1664914ee11SToomas Soome break; 1674914ee11SToomas Soome } 1684914ee11SToomas Soome /* else n < vd or n == vd */ 1694914ee11SToomas Soome vd->vdisk_unit++; 1704914ee11SToomas Soome continue; 1714914ee11SToomas Soome } 1724914ee11SToomas Soome /* p > vd only if p is the first element */ 1734914ee11SToomas Soome STAILQ_INSERT_HEAD(&vdisk_list, vd, vdisk_link); 1744914ee11SToomas Soome break; 1754914ee11SToomas Soome } 1764914ee11SToomas Soome 1774914ee11SToomas Soome /* if the list was empty or contiguous */ 1784914ee11SToomas Soome if (p == NULL) 1794914ee11SToomas Soome STAILQ_INSERT_TAIL(&vdisk_list, vd, vdisk_link); 1804914ee11SToomas Soome 1814914ee11SToomas Soome printf("%s: file %s is mapped as %s%d\n", argv[0], vd->vdisk_path, 1824914ee11SToomas Soome vdisk_dev.dv_name, vd->vdisk_unit); 1834914ee11SToomas Soome return (CMD_OK); 1844914ee11SToomas Soome } 1854914ee11SToomas Soome 1864914ee11SToomas Soome COMMAND_SET(unmap_vdisk, "unmap-vdisk", "unmap virtual disk", command_unmapvd); 1874914ee11SToomas Soome 1884914ee11SToomas Soome /* 1894914ee11SToomas Soome * unmap-vdisk vdiskX 1904914ee11SToomas Soome */ 1914914ee11SToomas Soome static int 1924914ee11SToomas Soome command_unmapvd(int argc, char *argv[]) 1934914ee11SToomas Soome { 1944914ee11SToomas Soome size_t len; 1954914ee11SToomas Soome vdisk_info_t *vd; 1964914ee11SToomas Soome long unit; 1974914ee11SToomas Soome char *end; 1984914ee11SToomas Soome 1994914ee11SToomas Soome if (argc != 2) { 2004914ee11SToomas Soome printf("usage: %s %sN\n", argv[0], vdisk_dev.dv_name); 2014914ee11SToomas Soome return (CMD_ERROR); 2024914ee11SToomas Soome } 2034914ee11SToomas Soome 2044914ee11SToomas Soome len = strlen(vdisk_dev.dv_name); 2054914ee11SToomas Soome if (strncmp(vdisk_dev.dv_name, argv[1], len) != 0) { 2064914ee11SToomas Soome printf("%s: unknown device %s\n", argv[0], argv[1]); 2074914ee11SToomas Soome return (CMD_ERROR); 2084914ee11SToomas Soome } 2094914ee11SToomas Soome errno = 0; 2104914ee11SToomas Soome unit = strtol(argv[1] + len, &end, 10); 2114914ee11SToomas Soome if (errno != 0 || (*end != '\0' && strcmp(end, ":") != 0)) { 2124914ee11SToomas Soome printf("%s: unknown device %s\n", argv[0], argv[1]); 2134914ee11SToomas Soome return (CMD_ERROR); 2144914ee11SToomas Soome } 2154914ee11SToomas Soome 2164914ee11SToomas Soome STAILQ_FOREACH(vd, &vdisk_list, vdisk_link) { 2174914ee11SToomas Soome if (vd->vdisk_unit == unit) 2184914ee11SToomas Soome break; 2194914ee11SToomas Soome } 2204914ee11SToomas Soome 2214914ee11SToomas Soome if (vd == NULL) { 2224914ee11SToomas Soome printf("%s: unknown device %s\n", argv[0], argv[1]); 2234914ee11SToomas Soome return (CMD_ERROR); 2244914ee11SToomas Soome } 2254914ee11SToomas Soome 2264914ee11SToomas Soome if (vd->vdisk_open != 0) { 2274914ee11SToomas Soome printf("%s: %s is in use, unable to unmap.\n", 2284914ee11SToomas Soome argv[0], argv[1]); 2294914ee11SToomas Soome return (CMD_ERROR); 2304914ee11SToomas Soome } 2314914ee11SToomas Soome 2324914ee11SToomas Soome STAILQ_REMOVE(&vdisk_list, vd, vdisk_info, vdisk_link); 23368031519SToomas Soome (void) close(vd->vdisk_fd); 23468031519SToomas Soome printf("%s (%s) unmapped\n", argv[1], vd->vdisk_path); 2354914ee11SToomas Soome free(vd->vdisk_path); 2364914ee11SToomas Soome free(vd); 2374914ee11SToomas Soome 2384914ee11SToomas Soome return (CMD_OK); 2394914ee11SToomas Soome } 2404914ee11SToomas Soome 2414914ee11SToomas Soome static int 2424914ee11SToomas Soome vdisk_init(void) 2434914ee11SToomas Soome { 2444914ee11SToomas Soome STAILQ_INIT(&vdisk_list); 2454914ee11SToomas Soome return (0); 2464914ee11SToomas Soome } 2474914ee11SToomas Soome 2484914ee11SToomas Soome static int 2494914ee11SToomas Soome vdisk_strategy(void *devdata, int rw, daddr_t blk, size_t size, 2504914ee11SToomas Soome char *buf, size_t *rsize) 2514914ee11SToomas Soome { 2524914ee11SToomas Soome struct disk_devdesc *dev; 2534914ee11SToomas Soome vdisk_info_t *vd; 2544914ee11SToomas Soome ssize_t rv; 2554914ee11SToomas Soome 2564914ee11SToomas Soome dev = devdata; 2574914ee11SToomas Soome if (dev == NULL) 2584914ee11SToomas Soome return (EINVAL); 2594914ee11SToomas Soome vd = vdisk_get_info((struct devdesc *)dev); 2604914ee11SToomas Soome if (vd == NULL) 2614914ee11SToomas Soome return (EINVAL); 2624914ee11SToomas Soome 2634914ee11SToomas Soome if (size == 0 || (size % 512) != 0) 2644914ee11SToomas Soome return (EIO); 2654914ee11SToomas Soome 2664914ee11SToomas Soome if (dev->dd.d_dev->dv_type == DEVT_DISK) { 2674914ee11SToomas Soome daddr_t offset; 2684914ee11SToomas Soome 2694914ee11SToomas Soome offset = dev->d_offset * vd->vdisk_sectorsz; 2704914ee11SToomas Soome offset /= 512; 2714914ee11SToomas Soome blk += offset; 2724914ee11SToomas Soome } 2734914ee11SToomas Soome if (lseek(vd->vdisk_fd, blk << 9, SEEK_SET) == -1) 2744914ee11SToomas Soome return (EIO); 2754914ee11SToomas Soome 2764914ee11SToomas Soome errno = 0; 2774914ee11SToomas Soome switch (rw & F_MASK) { 2784914ee11SToomas Soome case F_READ: 2794914ee11SToomas Soome rv = read(vd->vdisk_fd, buf, size); 2804914ee11SToomas Soome break; 2814914ee11SToomas Soome case F_WRITE: 2824914ee11SToomas Soome rv = write(vd->vdisk_fd, buf, size); 2834914ee11SToomas Soome break; 2844914ee11SToomas Soome default: 2854914ee11SToomas Soome return (ENOSYS); 2864914ee11SToomas Soome } 2874914ee11SToomas Soome 2884914ee11SToomas Soome if (errno == 0 && rsize != NULL) { 2894914ee11SToomas Soome *rsize = rv; 2904914ee11SToomas Soome } 2914914ee11SToomas Soome return (errno); 2924914ee11SToomas Soome } 2934914ee11SToomas Soome 2944914ee11SToomas Soome static int 2954914ee11SToomas Soome vdisk_open(struct open_file *f, ...) 2964914ee11SToomas Soome { 2974914ee11SToomas Soome va_list args; 2984914ee11SToomas Soome struct disk_devdesc *dev; 2994914ee11SToomas Soome vdisk_info_t *vd; 3004914ee11SToomas Soome int rc = 0; 3014914ee11SToomas Soome 3024914ee11SToomas Soome va_start(args, f); 3034914ee11SToomas Soome dev = va_arg(args, struct disk_devdesc *); 3044914ee11SToomas Soome va_end(args); 3054914ee11SToomas Soome if (dev == NULL) 3064914ee11SToomas Soome return (EINVAL); 3074914ee11SToomas Soome vd = vdisk_get_info((struct devdesc *)dev); 3084914ee11SToomas Soome if (vd == NULL) 3094914ee11SToomas Soome return (EINVAL); 3104914ee11SToomas Soome 3114914ee11SToomas Soome if (dev->dd.d_dev->dv_type == DEVT_DISK) { 3124914ee11SToomas Soome rc = disk_open(dev, vd->vdisk_size, vd->vdisk_sectorsz); 3134914ee11SToomas Soome } 3144914ee11SToomas Soome if (rc == 0) 3154914ee11SToomas Soome vd->vdisk_open++; 3164914ee11SToomas Soome return (rc); 3174914ee11SToomas Soome } 3184914ee11SToomas Soome 3194914ee11SToomas Soome static int 3204914ee11SToomas Soome vdisk_close(struct open_file *f) 3214914ee11SToomas Soome { 3224914ee11SToomas Soome struct disk_devdesc *dev; 3234914ee11SToomas Soome vdisk_info_t *vd; 3244914ee11SToomas Soome 3254914ee11SToomas Soome dev = (struct disk_devdesc *)(f->f_devdata); 3264914ee11SToomas Soome if (dev == NULL) 3274914ee11SToomas Soome return (EINVAL); 3284914ee11SToomas Soome vd = vdisk_get_info((struct devdesc *)dev); 3294914ee11SToomas Soome if (vd == NULL) 3304914ee11SToomas Soome return (EINVAL); 3314914ee11SToomas Soome 3324914ee11SToomas Soome vd->vdisk_open--; 3334914ee11SToomas Soome if (dev->dd.d_dev->dv_type == DEVT_DISK) 3344914ee11SToomas Soome return (disk_close(dev)); 3354914ee11SToomas Soome return (0); 3364914ee11SToomas Soome } 3374914ee11SToomas Soome 3384914ee11SToomas Soome static int 3394914ee11SToomas Soome vdisk_ioctl(struct open_file *f, u_long cmd, void *data) 3404914ee11SToomas Soome { 3414914ee11SToomas Soome struct disk_devdesc *dev; 3424914ee11SToomas Soome vdisk_info_t *vd; 3434914ee11SToomas Soome int rc; 3444914ee11SToomas Soome 3454914ee11SToomas Soome dev = (struct disk_devdesc *)(f->f_devdata); 3464914ee11SToomas Soome if (dev == NULL) 3474914ee11SToomas Soome return (EINVAL); 3484914ee11SToomas Soome vd = vdisk_get_info((struct devdesc *)dev); 3494914ee11SToomas Soome if (vd == NULL) 3504914ee11SToomas Soome return (EINVAL); 3514914ee11SToomas Soome 3524914ee11SToomas Soome if (dev->dd.d_dev->dv_type == DEVT_DISK) { 3534914ee11SToomas Soome rc = disk_ioctl(dev, cmd, data); 3544914ee11SToomas Soome if (rc != ENOTTY) 3554914ee11SToomas Soome return (rc); 3564914ee11SToomas Soome } 3574914ee11SToomas Soome 3584914ee11SToomas Soome switch (cmd) { 3594914ee11SToomas Soome case DIOCGSECTORSIZE: 3604914ee11SToomas Soome *(u_int *)data = vd->vdisk_sectorsz; 3614914ee11SToomas Soome break; 3624914ee11SToomas Soome case DIOCGMEDIASIZE: 3634914ee11SToomas Soome *(uint64_t *)data = vd->vdisk_size; 3644914ee11SToomas Soome break; 3654914ee11SToomas Soome default: 3664914ee11SToomas Soome return (ENOTTY); 3674914ee11SToomas Soome } 3684914ee11SToomas Soome return (0); 3694914ee11SToomas Soome } 3704914ee11SToomas Soome 3714914ee11SToomas Soome static int 3724914ee11SToomas Soome vdisk_print(int verbose) 3734914ee11SToomas Soome { 3744914ee11SToomas Soome int ret = 0; 3754914ee11SToomas Soome vdisk_info_t *vd; 3764914ee11SToomas Soome char line[80]; 3774914ee11SToomas Soome 3784914ee11SToomas Soome if (STAILQ_EMPTY(&vdisk_list)) 3794914ee11SToomas Soome return (ret); 3804914ee11SToomas Soome 3814914ee11SToomas Soome printf("%s devices:", vdisk_dev.dv_name); 3824914ee11SToomas Soome if ((ret = pager_output("\n")) != 0) 3834914ee11SToomas Soome return (ret); 3844914ee11SToomas Soome 3854914ee11SToomas Soome STAILQ_FOREACH(vd, &vdisk_list, vdisk_link) { 3864914ee11SToomas Soome struct disk_devdesc vd_dev; 3874914ee11SToomas Soome 3884914ee11SToomas Soome if (verbose) { 3894914ee11SToomas Soome printf(" %s", vd->vdisk_path); 3904914ee11SToomas Soome if ((ret = pager_output("\n")) != 0) 3914914ee11SToomas Soome break; 3924914ee11SToomas Soome } 3934914ee11SToomas Soome snprintf(line, sizeof(line), 3944914ee11SToomas Soome " %s%d", vdisk_dev.dv_name, vd->vdisk_unit); 3954914ee11SToomas Soome printf("%s: %" PRIu64 " X %u blocks", line, 3964914ee11SToomas Soome vd->vdisk_size / vd->vdisk_sectorsz, 3974914ee11SToomas Soome vd->vdisk_sectorsz); 3984914ee11SToomas Soome if ((ret = pager_output("\n")) != 0) 3994914ee11SToomas Soome break; 4004914ee11SToomas Soome 4014914ee11SToomas Soome vd_dev.dd.d_dev = &vdisk_dev; 4024914ee11SToomas Soome vd_dev.dd.d_unit = vd->vdisk_unit; 4034914ee11SToomas Soome vd_dev.d_slice = -1; 4044914ee11SToomas Soome vd_dev.d_partition = -1; 4054914ee11SToomas Soome 4064914ee11SToomas Soome ret = disk_open(&vd_dev, vd->vdisk_size, vd->vdisk_sectorsz); 4074914ee11SToomas Soome if (ret == 0) { 4084914ee11SToomas Soome ret = disk_print(&vd_dev, line, verbose); 4094914ee11SToomas Soome disk_close(&vd_dev); 4104914ee11SToomas Soome if (ret != 0) 4114914ee11SToomas Soome break; 4124914ee11SToomas Soome } else { 4134914ee11SToomas Soome ret = 0; 4144914ee11SToomas Soome } 4154914ee11SToomas Soome } 4164914ee11SToomas Soome 4174914ee11SToomas Soome return (ret); 4184914ee11SToomas Soome } 419