Rework disks to have pluggable backends.
authorccardenas <ccardenas@openbsd.org>
Sat, 25 Aug 2018 04:16:09 +0000 (04:16 +0000)
committerccardenas <ccardenas@openbsd.org>
Sat, 25 Aug 2018 04:16:09 +0000 (04:16 +0000)
This is prep work for adding qcow2 image support.

From Ori Bernstein.  Many thanks!

Tested by many.

OK ccardenas@

usr.sbin/vmd/Makefile
usr.sbin/vmd/vioraw.c [new file with mode: 0644]
usr.sbin/vmd/vioscsi.c
usr.sbin/vmd/virtio.c
usr.sbin/vmd/virtio.h

index 7ea090f..60616d3 100644 (file)
@@ -1,4 +1,4 @@
-#      $OpenBSD: Makefile,v 1.18 2018/06/28 02:21:15 gsoares Exp $
+#      $OpenBSD: Makefile,v 1.19 2018/08/25 04:16:09 ccardenas Exp $
 
 .if ${MACHINE} == "amd64" || ${MACHINE} == "i386"
 
@@ -6,7 +6,7 @@ PROG=           vmd
 SRCS=          vmd.c control.c log.c priv.c proc.c config.c vmm.c
 SRCS+=         vm.c loadfile_elf.c pci.c virtio.c i8259.c mc146818.c
 SRCS+=         ns8250.c i8253.c vmboot.c ufs.c disklabel.c dhcp.c packet.c
-SRCS+=         parse.y atomicio.c vioscsi.c
+SRCS+=         parse.y atomicio.c vioscsi.c vioraw.c
 
 CFLAGS+=       -Wall -I${.CURDIR}
 CFLAGS+=       -Wstrict-prototypes -Wmissing-prototypes
diff --git a/usr.sbin/vmd/vioraw.c b/usr.sbin/vmd/vioraw.c
new file mode 100644 (file)
index 0000000..4b87c64
--- /dev/null
@@ -0,0 +1,73 @@
+/*     $OpenBSD: vioraw.c,v 1.1 2018/08/25 04:16:09 ccardenas Exp $    */
+/*
+ * Copyright (c) 2018 Ori Bernstein <ori@eigenstate.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+
+#include <machine/vmmvar.h>
+#include <dev/pci/pcireg.h>
+
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "vmd.h"
+#include "vmm.h"
+#include "virtio.h"
+
+static ssize_t
+raw_pread(void *file, char *buf, size_t len, off_t off)
+{
+       return pread(*(int *)file, buf, len, off);
+}
+
+static ssize_t
+raw_pwrite(void *file, char *buf, size_t len, off_t off)
+{
+       return pwrite(*(int *)file, buf, len, off);
+}
+
+static void
+raw_close(void *file)
+{
+       close(*(int *)file);
+       free(file);
+}
+
+/*
+ * Initializes a raw disk image backing file from an fd.
+ * Stores the number of 512 byte sectors in *szp,
+ * returning -1 for error, 0 for success.
+ */
+int
+virtio_init_raw(struct virtio_backing *file, off_t *szp, int fd)
+{
+       off_t sz;
+       int *fdp;
+
+       sz = lseek(fd, 0, SEEK_END);
+       if (sz == -1)
+               return -1;
+
+       fdp = malloc(sizeof(int));
+       *fdp = fd;
+       file->p = fdp;
+       file->pread = raw_pread;
+       file->pwrite = raw_pwrite;
+       file->close = raw_close;
+       *szp = sz;
+       return 0;
+}
+
index 9386788..12fef2f 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: vioscsi.c,v 1.10 2018/07/15 20:25:52 ccardenas Exp $  */
+/*     $OpenBSD: vioscsi.c,v 1.11 2018/08/25 04:16:09 ccardenas Exp $  */
 
 /*
  * Copyright (c) 2017 Carlos Cardenas <ccardenas@openbsd.org>
@@ -197,7 +197,7 @@ vioscsi_start_read(struct vioscsi_dev *dev, off_t block, ssize_t n_blocks)
                goto nomem;
        info->len = n_blocks * VIOSCSI_BLOCK_SIZE_CDROM;
        info->offset = block * VIOSCSI_BLOCK_SIZE_CDROM;
-       info->fd = dev->fd;
+       info->file = &dev->file;
 
        return info;
 
@@ -210,7 +210,10 @@ nomem:
 static const uint8_t *
 vioscsi_finish_read(struct ioinfo *info)
 {
-       if (pread(info->fd, info->buf, info->len, info->offset) != info->len) {
+       struct virtio_backing *f;
+
+       f = info->file;
+       if (f->pread(f->p, info->buf, info->len, info->offset) != info->len) {
                info->error = errno;
                log_warn("vioscsi read error");
                return NULL;
index 4622ef4..df500a3 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: virtio.c,v 1.63 2018/07/09 16:11:37 mlarkin Exp $     */
+/*     $OpenBSD: virtio.c,v 1.64 2018/08/25 04:16:09 ccardenas Exp $   */
 
 /*
  * Copyright (c) 2015 Mike Larkin <mlarkin@openbsd.org>
@@ -361,7 +361,7 @@ vioblk_start_read(struct vioblk_dev *dev, off_t sector, ssize_t sz)
                goto nomem;
        info->len = sz;
        info->offset = sector * VIRTIO_BLK_SECTOR_SIZE;
-       info->fd = dev->fd;
+       info->file = &dev->file;
 
        return info;
 
@@ -375,7 +375,10 @@ nomem:
 static const uint8_t *
 vioblk_finish_read(struct ioinfo *info)
 {
-       if (pread(info->fd, info->buf, info->len, info->offset) != info->len) {
+       struct virtio_backing *file;
+
+       file = info->file;
+       if (file->pread(file->p, info->buf, info->len, info->offset) != info->len) {
                info->error = errno;
                log_warn("vioblk read error");
                return NULL;
@@ -398,7 +401,7 @@ vioblk_start_write(struct vioblk_dev *dev, off_t sector,
                goto nomem;
        info->len = len;
        info->offset = sector * VIRTIO_BLK_SECTOR_SIZE;
-       info->fd = dev->fd;
+       info->file = &dev->file;
 
        if (read_mem(addr, info->buf, len)) {
                vioblk_free_info(info);
@@ -416,7 +419,10 @@ nomem:
 static int
 vioblk_finish_write(struct ioinfo *info)
 {
-       if (pwrite(info->fd, info->buf, info->len, info->offset) != info->len) {
+       struct virtio_backing *file;
+
+       file = info->file;
+       if (file->pwrite(file->p, info->buf, info->len, info->offset) != info->len) {
                log_warn("vioblk write error");
                return EIO;
        }
@@ -1739,6 +1745,16 @@ vmmci_io(int dir, uint16_t reg, uint32_t *data, uint8_t *intr,
        return (0);
 }
 
+static int
+virtio_init_disk(struct virtio_backing *file, off_t *sz, int fd)
+{
+       /* 
+        * This is where we slot in disk type selection.
+        *  Right now, there's only raw.
+        */
+       return virtio_init_raw(file, sz, fd);
+}
+
 void
 virtio_init(struct vmd_vm *vm, int child_cdrom, int *child_disks,
     int *child_taps)
@@ -1748,7 +1764,6 @@ virtio_init(struct vmd_vm *vm, int child_cdrom, int *child_disks,
        uint8_t id;
        uint8_t i;
        int ret;
-       off_t sz;
 
        /* Virtio entropy device */
        if (pci_add_device(&id, PCI_VENDOR_QUMRANET,
@@ -1789,9 +1804,6 @@ virtio_init(struct vmd_vm *vm, int child_cdrom, int *child_disks,
 
                /* One virtio block device for each disk defined in vcp */
                for (i = 0; i < vcp->vcp_ndisks; i++) {
-                       if ((sz = lseek(child_disks[i], 0, SEEK_END)) == -1)
-                               continue;
-
                        if (pci_add_device(&id, PCI_VENDOR_QUMRANET,
                            PCI_PRODUCT_QUMRANET_VIO_BLOCK,
                            PCI_CLASS_MASS_STORAGE,
@@ -1815,13 +1827,15 @@ virtio_init(struct vmd_vm *vm, int child_cdrom, int *child_disks,
                            sizeof(struct vring_desc) * VIOBLK_QUEUE_SIZE
                            + sizeof(uint16_t) * (2 + VIOBLK_QUEUE_SIZE));
                        vioblk[i].vq[0].last_avail = 0;
-                       vioblk[i].fd = child_disks[i];
-                       vioblk[i].sz = sz / 512;
                        vioblk[i].cfg.device_feature = VIRTIO_BLK_F_SIZE_MAX;
                        vioblk[i].max_xfer = 1048576;
                        vioblk[i].pci_id = id;
                        vioblk[i].vm_id = vcp->vcp_id;
                        vioblk[i].irq = pci_get_dev_irq(id);
+                       if (virtio_init_disk(&vioblk[i].file, &vioblk[i].sz,
+                           child_disks[i]) == -1)
+                               continue;
+                       vioblk[i].sz /= 512;
                }
        }
 
@@ -1944,12 +1958,12 @@ virtio_init(struct vmd_vm *vm, int child_cdrom, int *child_disks,
                            + sizeof(uint16_t) * (2 + VIOSCSI_QUEUE_SIZE));
                        vioscsi->vq[i].last_avail = 0;
                }
-               sz = lseek(child_cdrom, 0, SEEK_END);
-               vioscsi->fd = child_cdrom;
+               if (virtio_init_disk(&vioscsi->file, &vioscsi->sz,
+                   child_cdrom) == -1)
+                       return;
                vioscsi->locked = 0;
                vioscsi->lba = 0;
-               vioscsi->sz = sz;
-               vioscsi->n_blocks = sz >> 11; /* num of 2048 blocks in file */
+               vioscsi->n_blocks = vioscsi->sz >> 11; /* num of 2048 blocks in file */
                vioscsi->max_xfer = VIOSCSI_BLOCK_SIZE_CDROM;
                vioscsi->pci_id = id;
                vioscsi->vm_id = vcp->vcp_id;
@@ -2087,7 +2101,6 @@ int
 vioblk_restore(int fd, struct vm_create_params *vcp, int *child_disks)
 {
        uint8_t i;
-       off_t sz;
 
        nr_vioblk = vcp->vcp_ndisks;
        vioblk = calloc(vcp->vcp_ndisks, sizeof(struct vioblk_dev));
@@ -2103,16 +2116,15 @@ vioblk_restore(int fd, struct vm_create_params *vcp, int *child_disks)
                return (-1);
        }
        for (i = 0; i < vcp->vcp_ndisks; i++) {
-               if ((sz = lseek(child_disks[i], 0, SEEK_END)) == -1)
-                       continue;
-
                if (pci_set_bar_fn(vioblk[i].pci_id, 0, virtio_blk_io,
                    &vioblk[i])) {
                        log_warnx("%s: can't set bar fn for virtio block "
                            "device", __progname);
                        return (-1);
                }
-               vioblk[i].fd = child_disks[i];
+               if (virtio_init_disk(&vioblk[i].file, &vioblk[i].sz,
+                    child_disks[i]) == -1)
+                       continue;
        }
        return (0);
 }
@@ -2120,8 +2132,6 @@ vioblk_restore(int fd, struct vm_create_params *vcp, int *child_disks)
 int
 vioscsi_restore(int fd, struct vm_create_params *vcp, int child_cdrom)
 {
-       off_t sz;
-
        if (!strlen(vcp->vcp_cdrom))
                return (0);
 
@@ -2139,15 +2149,13 @@ vioscsi_restore(int fd, struct vm_create_params *vcp, int child_cdrom)
                return (-1);
        }
 
-       sz = lseek(child_cdrom, 0, SEEK_END);
-
        if (pci_set_bar_fn(vioscsi->pci_id, 0, vioscsi_io, vioscsi)) {
                log_warnx("%s: can't set bar fn for vmm control device",
                    __progname);
                return (-1);
        }
 
-       vioscsi->fd = child_cdrom;
+       virtio_init_disk(&vioscsi->file, &vioscsi->sz, child_cdrom);
 
        return (0);
 }
index 20327f9..84a7e2a 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: virtio.h,v 1.26 2018/07/09 08:43:09 mlarkin Exp $     */
+/*     $OpenBSD: virtio.h,v 1.27 2018/08/25 04:16:09 ccardenas Exp $   */
 
 /*
  * Copyright (c) 2015 Mike Larkin <mlarkin@openbsd.org>
@@ -61,6 +61,13 @@ struct virtio_io_cfg {
        uint8_t isr_status;
 };
 
+struct virtio_backing {
+       void  *p;
+       ssize_t  (*pread)(void *p, char *buf, size_t len, off_t off);
+       ssize_t  (*pwrite)(void *p, char *buf, size_t len, off_t off);
+       void (*close)(void *p);
+};
+
 /*
  * A virtio device can have several virtqs. For example, vionet has one virtq
  * each for transmitting and receiving packets. This struct describes the state
@@ -147,8 +154,8 @@ struct vioblk_dev {
        struct virtio_io_cfg cfg;
 
        struct virtio_vq_info vq[VIRTIO_MAX_QUEUES];
+       struct virtio_backing file;
 
-       int fd;
        uint64_t sz;
        uint32_t max_xfer;
 
@@ -168,9 +175,10 @@ struct vioscsi_dev {
 
        struct virtio_vq_info vq[VIRTIO_MAX_QUEUES];
 
+       struct virtio_backing file;
+
        /* is the device locked */
        int locked;
-       int fd;
        /* size of iso file in bytes */
        uint64_t sz;
        /* last block address read */
@@ -241,10 +249,10 @@ struct vmmci_dev {
 };
 
 struct ioinfo {
+       struct virtio_backing *file;
        uint8_t *buf;
        ssize_t len;
        off_t offset;
-       int fd;
        int error;
 };
 
@@ -261,6 +269,8 @@ void viornd_update_qs(void);
 void viornd_update_qa(void);
 int viornd_notifyq(void);
 
+int virtio_init_raw(struct virtio_backing *dev, off_t *sz, int fd);
+
 int virtio_blk_io(int, uint16_t, uint32_t *, uint8_t *, void *, uint8_t);
 int vioblk_dump(int);
 int vioblk_restore(int, struct vm_create_params *, int *);