From a76bb44da4877b1cb5896e5648aef10a757eece0 Mon Sep 17 00:00:00 2001 From: tedu Date: Tue, 30 May 2017 17:56:47 +0000 Subject: [PATCH] split vioblk read/write functions into start and finish as prep for async io operations. ok mlarkin --- usr.sbin/vmd/virtio.c | 140 +++++++++++++++++++++++++++++------------- usr.sbin/vmd/vm.c | 7 ++- usr.sbin/vmd/vmd.h | 4 +- 3 files changed, 104 insertions(+), 47 deletions(-) diff --git a/usr.sbin/vmd/virtio.c b/usr.sbin/vmd/virtio.c index 38469c49ddc..83238429bd4 100644 --- a/usr.sbin/vmd/virtio.c +++ b/usr.sbin/vmd/virtio.c @@ -1,4 +1,4 @@ -/* $OpenBSD: virtio.c,v 1.48 2017/05/30 13:13:47 mlarkin Exp $ */ +/* $OpenBSD: virtio.c,v 1.49 2017/05/30 17:56:47 tedu Exp $ */ /* * Copyright (c) 2015 Mike Larkin @@ -62,6 +62,14 @@ int nr_vioblk; #define VMMCI_F_ACK (1<<1) #define VMMCI_F_SYNCRTC (1<<2) +struct ioinfo { + uint8_t *buf; + ssize_t len; + off_t offset; + int fd; + int error; +}; + const char * vioblk_cmd_name(uint32_t type) { @@ -324,35 +332,87 @@ vioblk_update_qs(struct vioblk_dev *dev) dev->cfg.queue_size = dev->vq[dev->cfg.queue_select].qs; } -static char * -vioblk_do_read(struct vioblk_dev *dev, off_t sector, ssize_t sz) +static void +vioblk_free_info(struct ioinfo *info) { - char *buf; + if (!info) + return; + free(info->buf); + free(info); +} - buf = malloc(sz); - if (buf == NULL) { - log_warn("malloc errror vioblk read"); - return (NULL); - } +static struct ioinfo * +vioblk_start_read(struct vioblk_dev *dev, off_t sector, ssize_t sz) +{ + struct ioinfo *info; + + info = calloc(1, sizeof(*info)); + if (!info) + goto nomem; + info->buf = malloc(sz); + if (info->buf == NULL) + goto nomem; + info->len = sz; + info->offset = sector * VIRTIO_BLK_SECTOR_SIZE; + info->fd = dev->fd; + + return info; + +nomem: + free(info); + log_warn("malloc errror vioblk read"); + return (NULL); +} - if (pread(dev->fd, buf, sz, sector * VIRTIO_BLK_SECTOR_SIZE) != sz) { + +static const uint8_t * +vioblk_finish_read(struct ioinfo *info) +{ + if (pread(info->fd, info->buf, info->len, info->offset) != info->len) { + info->error = errno; log_warn("vioblk read error"); - free(buf); - return (NULL); + return NULL; } - return buf; + return info->buf; +} + +static struct ioinfo * +vioblk_start_write(struct vioblk_dev *dev, off_t sector, paddr_t addr, size_t len) +{ + struct ioinfo *info; + + info = calloc(1, sizeof(*info)); + if (!info) + goto nomem; + info->buf = malloc(len); + if (info->buf == NULL) + goto nomem; + info->len = len; + info->offset = sector * VIRTIO_BLK_SECTOR_SIZE; + info->fd = dev->fd; + + if (read_mem(addr, info->buf, len)) { + vioblk_free_info(info); + return NULL; + } + + return info; + +nomem: + free(info); + log_warn("malloc errror vioblk write"); + return (NULL); } static int -vioblk_do_write(struct vioblk_dev *dev, off_t sector, char *buf, ssize_t sz) +vioblk_finish_write(struct ioinfo *info) { - if (pwrite(dev->fd, buf, sz, sector * VIRTIO_BLK_SECTOR_SIZE) != sz) { + if (pwrite(info->fd, info->buf, info->len, info->offset) != info->len) { log_warn("vioblk write error"); - return (1); + return EIO; } - - return (0); + return 0; } /* @@ -368,7 +428,7 @@ vioblk_notifyq(struct vioblk_dev *dev) uint8_t ds; int ret; off_t secbias; - char *vr, *secdata; + char *vr; struct vring_desc *desc, *cmd_desc, *secdata_desc, *ds_desc; struct vring_avail *avail; struct vring_used *used; @@ -441,14 +501,16 @@ vioblk_notifyq(struct vioblk_dev *dev) secbias = 0; do { - /* read the data (use current data descriptor) */ - /* - * XXX waste to malloc secdata in vioblk_do_read - * and free it here over and over - */ - secdata = vioblk_do_read(dev, cmd.sector + secbias, + struct ioinfo *info; + const uint8_t *secdata; + + info = vioblk_start_read(dev, cmd.sector + secbias, (ssize_t)secdata_desc->len); + + /* read the data (use current data descriptor) */ + secdata = vioblk_finish_read(info); if (secdata == NULL) { + vioblk_free_info(info); log_warnx("vioblk: block read error, " "sector %lld", cmd.sector); goto out; @@ -460,11 +522,11 @@ vioblk_notifyq(struct vioblk_dev *dev) "data to gpa @ 0x%llx", secdata_desc->addr); dump_descriptor_chain(desc, cmd_desc_idx); - free(secdata); + vioblk_free_info(info); goto out; } - free(secdata); + vioblk_free_info(info); secbias += (secdata_desc->len / VIRTIO_BLK_SECTOR_SIZE); secdata_desc_idx = secdata_desc->next & @@ -514,35 +576,31 @@ vioblk_notifyq(struct vioblk_dev *dev) goto out; } - secdata = NULL; secbias = 0; do { - secdata = realloc(secdata, secdata_desc->len); - if (secdata == NULL) { - log_warn("wr vioblk: malloc error, " - "len %d", secdata_desc->len); - goto out; - } + struct ioinfo *info; - if (read_mem(secdata_desc->addr, secdata, - secdata_desc->len)) { + info = vioblk_start_write(dev, cmd.sector + secbias, + secdata_desc->addr, secdata_desc->len); + + if (info == NULL) { log_warnx("wr vioblk: can't read " "sector data @ 0x%llx", secdata_desc->addr); dump_descriptor_chain(desc, cmd_desc_idx); - free(secdata); goto out; } - if (vioblk_do_write(dev, cmd.sector + secbias, - secdata, (ssize_t)secdata_desc->len)) { + if (vioblk_finish_write(info)) { log_warnx("wr vioblk: disk write " "error"); - free(secdata); + vioblk_free_info(info); goto out; } + vioblk_free_info(info); + secbias += secdata_desc->len / VIRTIO_BLK_SECTOR_SIZE; @@ -551,8 +609,6 @@ vioblk_notifyq(struct vioblk_dev *dev) secdata_desc = &desc[secdata_desc_idx]; } while (secdata_desc->flags & VRING_DESC_F_NEXT); - free(secdata); - ds_desc_idx = secdata_desc_idx; ds_desc = secdata_desc; diff --git a/usr.sbin/vmd/vm.c b/usr.sbin/vmd/vm.c index 81f7b0ffb7c..2d38bc0f5e3 100644 --- a/usr.sbin/vmd/vm.c +++ b/usr.sbin/vmd/vm.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vm.c,v 1.18 2017/05/28 23:56:13 mlarkin Exp $ */ +/* $OpenBSD: vm.c,v 1.19 2017/05/30 17:56:47 tedu Exp $ */ /* * Copyright (c) 2015 Mike Larkin @@ -1230,9 +1230,10 @@ find_gpa_range(struct vm_create_params *vcp, paddr_t gpa, size_t len) * exist in the guest. */ int -write_mem(paddr_t dst, void *buf, size_t len) +write_mem(paddr_t dst, const void *buf, size_t len) { - char *from = buf, *to; + const char *from = buf; + char *to; size_t n, off; struct vm_mem_range *vmr; diff --git a/usr.sbin/vmd/vmd.h b/usr.sbin/vmd/vmd.h index 05294c98897..a24c959de3e 100644 --- a/usr.sbin/vmd/vmd.h +++ b/usr.sbin/vmd/vmd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: vmd.h,v 1.54 2017/05/04 19:41:58 reyk Exp $ */ +/* $OpenBSD: vmd.h,v 1.55 2017/05/30 17:56:47 tedu Exp $ */ /* * Copyright (c) 2015 Mike Larkin @@ -289,7 +289,7 @@ uint32_t vm_priv_addr(struct address *, uint32_t, int, int); /* vmm.c */ void vmm(struct privsep *, struct privsep_proc *); void vmm_shutdown(void); -int write_mem(paddr_t, void *buf, size_t); +int write_mem(paddr_t, const void *buf, size_t); int read_mem(paddr_t, void *buf, size_t); int opentap(char *); int fd_hasdata(int); -- 2.20.1