Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F171822636
D19733.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
12 KB
Referenced Files
None
Subscribers
None
D19733.diff
View Options
Index: head/stand/common/help.common
===================================================================
--- head/stand/common/help.common
+++ head/stand/common/help.common
@@ -99,6 +99,13 @@
List loaded modules. If [-v] is specified, print more details.
################################################################################
+# Tmap-vdisk DMap virtual disk
+
+ map-vdisk filename
+
+ Map file as virtual disk.
+
+################################################################################
# Tmore DPage files
more <filename> [<filename> ...]
@@ -395,6 +402,13 @@
unload
This command removes any kernel and all loaded modules from memory.
+
+################################################################################
+# Tunmap-vdisk DUnmap virtual disk
+
+ unmap-vdisk diskname
+
+ Delete virtual disk mapping.
################################################################################
# Tunset DUnset a variable
Index: head/stand/common/vdisk.c
===================================================================
--- head/stand/common/vdisk.c
+++ head/stand/common/vdisk.c
@@ -0,0 +1,417 @@
+/*-
+ * Copyright 2019 Toomas Soome <tsoome@me.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stand.h>
+#include <stdarg.h>
+#include <machine/_inttypes.h>
+#include <bootstrap.h>
+#include <sys/disk.h>
+#include <sys/errno.h>
+#include <sys/queue.h>
+#include <sys/param.h>
+#include <disk.h>
+
+static int vdisk_init(void);
+static int vdisk_strategy(void *, int, daddr_t, size_t, char *, size_t *);
+static int vdisk_open(struct open_file *, ...);
+static int vdisk_close(struct open_file *);
+static int vdisk_ioctl(struct open_file *, u_long, void *);
+static int vdisk_print(int);
+
+struct devsw vdisk_dev = {
+ .dv_name = "vdisk",
+ .dv_type = DEVT_DISK,
+ .dv_init = vdisk_init,
+ .dv_strategy = vdisk_strategy,
+ .dv_open = vdisk_open,
+ .dv_close = vdisk_close,
+ .dv_ioctl = vdisk_ioctl,
+ .dv_print = vdisk_print,
+ .dv_cleanup = NULL
+};
+
+typedef STAILQ_HEAD(vdisk_info_list, vdisk_info) vdisk_info_list_t;
+
+typedef struct vdisk_info
+{
+ STAILQ_ENTRY(vdisk_info) vdisk_link; /* link in device list */
+ char *vdisk_path;
+ int vdisk_unit;
+ int vdisk_fd;
+ uint64_t vdisk_size; /* size in bytes */
+ uint32_t vdisk_sectorsz;
+ uint32_t vdisk_open; /* reference counter */
+} vdisk_info_t;
+
+static vdisk_info_list_t vdisk_list; /* list of mapped vdisks. */
+
+static vdisk_info_t *
+vdisk_get_info(struct devdesc *dev)
+{
+ vdisk_info_t *vd;
+
+ STAILQ_FOREACH(vd, &vdisk_list, vdisk_link) {
+ if (vd->vdisk_unit == dev->d_unit)
+ return (vd);
+ }
+ return (vd);
+}
+
+COMMAND_SET(map_vdisk, "map-vdisk", "map file as virtual disk", command_mapvd);
+
+static int
+command_mapvd(int argc, char *argv[])
+{
+ vdisk_info_t *vd, *p;
+ struct stat sb;
+
+ if (argc != 2) {
+ printf("usage: %s filename\n", argv[0]);
+ return (CMD_ERROR);
+ }
+
+ STAILQ_FOREACH(vd, &vdisk_list, vdisk_link) {
+ if (strcmp(vd->vdisk_path, argv[1]) == 0) {
+ printf("%s: file %s is already mapped as %s%d\n",
+ argv[0], argv[1], vdisk_dev.dv_name,
+ vd->vdisk_unit);
+ return (CMD_ERROR);
+ }
+ }
+
+ if (stat(argv[1], &sb) < 0) {
+ /*
+ * ENOSYS is really ENOENT because we did try to walk
+ * through devsw list to try to open this file.
+ */
+ if (errno == ENOSYS)
+ errno = ENOENT;
+
+ printf("%s: stat failed: %s\n", argv[0], strerror(errno));
+ return (CMD_ERROR);
+ }
+
+ /*
+ * Avoid mapping small files.
+ */
+ if (sb.st_size < 1024 * 1024) {
+ printf("%s: file %s is too small.\n", argv[0], argv[1]);
+ return (CMD_ERROR);
+ }
+
+ vd = calloc(1, sizeof (*vd));
+ if (vd == NULL) {
+ printf("%s: out of memory\n", argv[0]);
+ return (CMD_ERROR);
+ }
+ vd->vdisk_path = strdup(argv[1]);
+ if (vd->vdisk_path == NULL) {
+ free (vd);
+ printf("%s: out of memory\n", argv[0]);
+ return (CMD_ERROR);
+ }
+ vd->vdisk_fd = open(vd->vdisk_path, O_RDONLY);
+ if (vd->vdisk_fd < 0) {
+ printf("%s: open failed: %s\n", argv[0], strerror(errno));
+ free(vd->vdisk_path);
+ free(vd);
+ return (CMD_ERROR);
+ }
+
+ vd->vdisk_size = sb.st_size;
+ vd->vdisk_sectorsz = DEV_BSIZE;
+ STAILQ_FOREACH(p, &vdisk_list, vdisk_link) {
+ vdisk_info_t *n;
+ if (p->vdisk_unit == vd->vdisk_unit) {
+ vd->vdisk_unit++;
+ continue;
+ }
+ n = STAILQ_NEXT(p, vdisk_link);
+ if (p->vdisk_unit < vd->vdisk_unit) {
+ if (n == NULL) {
+ /* p is last elem */
+ STAILQ_INSERT_TAIL(&vdisk_list, vd, vdisk_link);
+ break;
+ }
+ if (n->vdisk_unit > vd->vdisk_unit) {
+ /* p < vd < n */
+ STAILQ_INSERT_AFTER(&vdisk_list, p, vd,
+ vdisk_link);
+ break;
+ }
+ /* else n < vd or n == vd */
+ vd->vdisk_unit++;
+ continue;
+ }
+ /* p > vd only if p is the first element */
+ STAILQ_INSERT_HEAD(&vdisk_list, vd, vdisk_link);
+ break;
+ }
+
+ /* if the list was empty or contiguous */
+ if (p == NULL)
+ STAILQ_INSERT_TAIL(&vdisk_list, vd, vdisk_link);
+
+ printf("%s: file %s is mapped as %s%d\n", argv[0], vd->vdisk_path,
+ vdisk_dev.dv_name, vd->vdisk_unit);
+ return (CMD_OK);
+}
+
+COMMAND_SET(unmap_vdisk, "unmap-vdisk", "unmap virtual disk", command_unmapvd);
+
+/*
+ * unmap-vdisk vdiskX
+ */
+static int
+command_unmapvd(int argc, char *argv[])
+{
+ size_t len;
+ vdisk_info_t *vd;
+ long unit;
+ char *end;
+
+ if (argc != 2) {
+ printf("usage: %s %sN\n", argv[0], vdisk_dev.dv_name);
+ return (CMD_ERROR);
+ }
+
+ len = strlen(vdisk_dev.dv_name);
+ if (strncmp(vdisk_dev.dv_name, argv[1], len) != 0) {
+ printf("%s: unknown device %s\n", argv[0], argv[1]);
+ return (CMD_ERROR);
+ }
+ errno = 0;
+ unit = strtol(argv[1] + len, &end, 10);
+ if (errno != 0 || (*end != '\0' && strcmp(end, ":") != 0)) {
+ printf("%s: unknown device %s\n", argv[0], argv[1]);
+ return (CMD_ERROR);
+ }
+
+ STAILQ_FOREACH(vd, &vdisk_list, vdisk_link) {
+ if (vd->vdisk_unit == unit)
+ break;
+ }
+
+ if (vd == NULL) {
+ printf("%s: unknown device %s\n", argv[0], argv[1]);
+ return (CMD_ERROR);
+ }
+
+ if (vd->vdisk_open != 0) {
+ printf("%s: %s is in use, unable to unmap.\n",
+ argv[0], argv[1]);
+ return (CMD_ERROR);
+ }
+
+ STAILQ_REMOVE(&vdisk_list, vd, vdisk_info, vdisk_link);
+ close(vd->vdisk_fd);
+ free(vd->vdisk_path);
+ free(vd);
+ printf("%s (%s) unmapped\n", argv[1], vd->vdisk_path);
+
+ return (CMD_OK);
+}
+
+static int
+vdisk_init(void)
+{
+ STAILQ_INIT(&vdisk_list);
+ return (0);
+}
+
+static int
+vdisk_strategy(void *devdata, int rw, daddr_t blk, size_t size,
+ char *buf, size_t *rsize)
+{
+ struct disk_devdesc *dev;
+ vdisk_info_t *vd;
+ ssize_t rv;
+
+ dev = devdata;
+ if (dev == NULL)
+ return (EINVAL);
+ vd = vdisk_get_info((struct devdesc *)dev);
+ if (vd == NULL)
+ return (EINVAL);
+
+ if (size == 0 || (size % 512) != 0)
+ return (EIO);
+
+ if (dev->dd.d_dev->dv_type == DEVT_DISK) {
+ daddr_t offset;
+
+ offset = dev->d_offset * vd->vdisk_sectorsz;
+ offset /= 512;
+ blk += offset;
+ }
+ if (lseek(vd->vdisk_fd, blk << 9, SEEK_SET) == -1)
+ return (EIO);
+
+ errno = 0;
+ switch (rw & F_MASK) {
+ case F_READ:
+ rv = read(vd->vdisk_fd, buf, size);
+ break;
+ case F_WRITE:
+ rv = write(vd->vdisk_fd, buf, size);
+ break;
+ default:
+ return (ENOSYS);
+ }
+
+ if (errno == 0 && rsize != NULL) {
+ *rsize = rv;
+ }
+ return (errno);
+}
+
+static int
+vdisk_open(struct open_file *f, ...)
+{
+ va_list args;
+ struct disk_devdesc *dev;
+ vdisk_info_t *vd;
+ int rc = 0;
+
+ va_start(args, f);
+ dev = va_arg(args, struct disk_devdesc *);
+ va_end(args);
+ if (dev == NULL)
+ return (EINVAL);
+ vd = vdisk_get_info((struct devdesc *)dev);
+ if (vd == NULL)
+ return (EINVAL);
+
+ if (dev->dd.d_dev->dv_type == DEVT_DISK) {
+ rc = disk_open(dev, vd->vdisk_size, vd->vdisk_sectorsz);
+ }
+ if (rc == 0)
+ vd->vdisk_open++;
+ return (rc);
+}
+
+static int
+vdisk_close(struct open_file *f)
+{
+ struct disk_devdesc *dev;
+ vdisk_info_t *vd;
+
+ dev = (struct disk_devdesc *)(f->f_devdata);
+ if (dev == NULL)
+ return (EINVAL);
+ vd = vdisk_get_info((struct devdesc *)dev);
+ if (vd == NULL)
+ return (EINVAL);
+
+ vd->vdisk_open--;
+ if (dev->dd.d_dev->dv_type == DEVT_DISK)
+ return (disk_close(dev));
+ return (0);
+}
+
+static int
+vdisk_ioctl(struct open_file *f, u_long cmd, void *data)
+{
+ struct disk_devdesc *dev;
+ vdisk_info_t *vd;
+ int rc;
+
+ dev = (struct disk_devdesc *)(f->f_devdata);
+ if (dev == NULL)
+ return (EINVAL);
+ vd = vdisk_get_info((struct devdesc *)dev);
+ if (vd == NULL)
+ return (EINVAL);
+
+ if (dev->dd.d_dev->dv_type == DEVT_DISK) {
+ rc = disk_ioctl(dev, cmd, data);
+ if (rc != ENOTTY)
+ return (rc);
+ }
+
+ switch (cmd) {
+ case DIOCGSECTORSIZE:
+ *(u_int *)data = vd->vdisk_sectorsz;
+ break;
+ case DIOCGMEDIASIZE:
+ *(uint64_t *)data = vd->vdisk_size;
+ break;
+ default:
+ return (ENOTTY);
+ }
+ return (0);
+}
+
+static int
+vdisk_print(int verbose)
+{
+ int ret = 0;
+ vdisk_info_t *vd;
+ char line[80];
+
+ if (STAILQ_EMPTY(&vdisk_list))
+ return (ret);
+
+ printf("%s devices:", vdisk_dev.dv_name);
+ if ((ret = pager_output("\n")) != 0)
+ return (ret);
+
+ STAILQ_FOREACH(vd, &vdisk_list, vdisk_link) {
+ struct disk_devdesc vd_dev;
+
+ if (verbose) {
+ printf(" %s", vd->vdisk_path);
+ if ((ret = pager_output("\n")) != 0)
+ break;
+ }
+ snprintf(line, sizeof(line),
+ " %s%d", vdisk_dev.dv_name, vd->vdisk_unit);
+ printf("%s: %" PRIu64 " X %u blocks", line,
+ vd->vdisk_size / vd->vdisk_sectorsz,
+ vd->vdisk_sectorsz);
+ if ((ret = pager_output("\n")) != 0)
+ break;
+
+ vd_dev.dd.d_dev = &vdisk_dev;
+ vd_dev.dd.d_unit = vd->vdisk_unit;
+ vd_dev.d_slice = -1;
+ vd_dev.d_partition = -1;
+
+ ret = disk_open(&vd_dev, vd->vdisk_size, vd->vdisk_sectorsz);
+ if (ret == 0) {
+ ret = disk_print(&vd_dev, line, verbose);
+ disk_close(&vd_dev);
+ if (ret != 0)
+ break;
+ } else {
+ ret = 0;
+ }
+ }
+
+ return (ret);
+}
Index: head/stand/efi/loader/conf.c
===================================================================
--- head/stand/efi/loader/conf.c
+++ head/stand/efi/loader/conf.c
@@ -33,11 +33,14 @@
#include <efilib.h>
#include <efizfs.h>
+extern struct devsw vdisk_dev;
+
struct devsw *devsw[] = {
&efipart_fddev,
&efipart_cddev,
&efipart_hddev,
&efinet_dev,
+ &vdisk_dev,
#ifdef EFI_ZFS_BOOT
&zfs_dev,
#endif
Index: head/stand/i386/loader/conf.c
===================================================================
--- head/stand/i386/loader/conf.c
+++ head/stand/i386/loader/conf.c
@@ -48,6 +48,7 @@
#if defined(LOADER_FIREWIRE_SUPPORT)
extern struct devsw fwohci;
#endif
+extern struct devsw vdisk_dev;
/* Exported for libstand */
struct devsw *devsw[] = {
@@ -60,6 +61,7 @@
#if defined(LOADER_FIREWIRE_SUPPORT)
&fwohci,
#endif
+ &vdisk_dev,
#if defined(LOADER_ZFS_SUPPORT)
&zfs_dev,
#endif
Index: head/stand/loader.mk
===================================================================
--- head/stand/loader.mk
+++ head/stand/loader.mk
@@ -31,7 +31,7 @@
.endif
.if ${LOADER_DISK_SUPPORT:Uyes} == "yes"
-SRCS+= disk.c part.c
+SRCS+= disk.c part.c vdisk.c
.endif
.if ${LOADER_NET_SUPPORT:Uno} == "yes"
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Sep 14, 7:49 PM (15 h, 22 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
38923524
Default Alt Text
D19733.diff (12 KB)
Attached To
Mode
D19733: loader: implement map-vdisk and unmap-vdisk commands
Attached
Detach File
Event Timeline
Log In to Comment