From 9617633b7f0fd3591eb4ab25fa928acf80e426f5 Mon Sep 17 00:00:00 2001 From: ccardenas Date: Sat, 25 Aug 2018 04:16:09 +0000 Subject: [PATCH] Rework disks to have pluggable backends. This is prep work for adding qcow2 image support. From Ori Bernstein. Many thanks! Tested by many. OK ccardenas@ --- usr.sbin/vmd/Makefile | 4 +-- usr.sbin/vmd/vioraw.c | 73 ++++++++++++++++++++++++++++++++++++++++++ usr.sbin/vmd/vioscsi.c | 9 ++++-- usr.sbin/vmd/virtio.c | 58 ++++++++++++++++++--------------- usr.sbin/vmd/virtio.h | 18 ++++++++--- 5 files changed, 128 insertions(+), 34 deletions(-) create mode 100644 usr.sbin/vmd/vioraw.c diff --git a/usr.sbin/vmd/Makefile b/usr.sbin/vmd/Makefile index 7ea090f8886..60616d39167 100644 --- a/usr.sbin/vmd/Makefile +++ b/usr.sbin/vmd/Makefile @@ -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 index 00000000000..4b87c649407 --- /dev/null +++ b/usr.sbin/vmd/vioraw.c @@ -0,0 +1,73 @@ +/* $OpenBSD: vioraw.c,v 1.1 2018/08/25 04:16:09 ccardenas Exp $ */ +/* + * Copyright (c) 2018 Ori Bernstein + * + * 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 + +#include +#include + +#include +#include + +#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; +} + diff --git a/usr.sbin/vmd/vioscsi.c b/usr.sbin/vmd/vioscsi.c index 93867887598..12fef2f4778 100644 --- a/usr.sbin/vmd/vioscsi.c +++ b/usr.sbin/vmd/vioscsi.c @@ -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 @@ -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; diff --git a/usr.sbin/vmd/virtio.c b/usr.sbin/vmd/virtio.c index 4622ef4943f..df500a385ce 100644 --- a/usr.sbin/vmd/virtio.c +++ b/usr.sbin/vmd/virtio.c @@ -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 @@ -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); } diff --git a/usr.sbin/vmd/virtio.h b/usr.sbin/vmd/virtio.h index 20327f9915c..84a7e2af6a5 100644 --- a/usr.sbin/vmd/virtio.h +++ b/usr.sbin/vmd/virtio.h @@ -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 @@ -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 *); -- 2.20.1