[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH v4 09/22] vhost: use a function for each call
From: |
Thibaut Collet |
Subject: |
Re: [Qemu-devel] [PATCH v4 09/22] vhost: use a function for each call |
Date: |
Mon, 21 Sep 2015 09:33:04 +0200 |
On Sat, Sep 19, 2015 at 12:12 PM, <address@hidden> wrote:
> From: Marc-André Lureau <address@hidden>
>
> Replace the generic vhost_call() by specific functions for each
> function call to help with type safety and changing arguments.
>
> Signed-off-by: Marc-André Lureau <address@hidden>
> ---
> hw/net/vhost_net.c | 12 +-
> hw/scsi/vhost-scsi.c | 7 +-
> hw/virtio/vhost-backend.c | 140 +++++++++++--
> hw/virtio/vhost-user.c | 402
> ++++++++++++++++++++++++++------------
> hw/virtio/vhost.c | 34 ++--
> include/hw/virtio/vhost-backend.h | 59 +++++-
> 6 files changed, 484 insertions(+), 170 deletions(-)
>
> diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
> index 9d32d76..d116fb3 100644
> --- a/hw/net/vhost_net.c
> +++ b/hw/net/vhost_net.c
> @@ -243,8 +243,7 @@ static int vhost_net_start_one(struct vhost_net *net,
> file.fd = net->backend;
> for (file.index = 0; file.index < net->dev.nvqs; ++file.index) {
> const VhostOps *vhost_ops = net->dev.vhost_ops;
> - r = vhost_ops->vhost_call(&net->dev, VHOST_NET_SET_BACKEND,
> - &file);
> + r = vhost_ops->vhost_net_set_backend(&net->dev, &file);
> if (r < 0) {
> r = -errno;
> goto fail;
> @@ -257,8 +256,7 @@ fail:
> if (net->nc->info->type == NET_CLIENT_OPTIONS_KIND_TAP) {
> while (file.index-- > 0) {
> const VhostOps *vhost_ops = net->dev.vhost_ops;
> - int r = vhost_ops->vhost_call(&net->dev, VHOST_NET_SET_BACKEND,
> - &file);
> + int r = vhost_ops->vhost_net_set_backend(&net->dev, &file);
> assert(r >= 0);
> }
> }
> @@ -280,15 +278,13 @@ static void vhost_net_stop_one(struct vhost_net *net,
> if (net->nc->info->type == NET_CLIENT_OPTIONS_KIND_TAP) {
> for (file.index = 0; file.index < net->dev.nvqs; ++file.index) {
> const VhostOps *vhost_ops = net->dev.vhost_ops;
> - int r = vhost_ops->vhost_call(&net->dev, VHOST_NET_SET_BACKEND,
> - &file);
> + int r = vhost_ops->vhost_net_set_backend(&net->dev, &file);
> assert(r >= 0);
> }
> } else if (net->nc->info->type == NET_CLIENT_OPTIONS_KIND_VHOST_USER) {
> for (file.index = 0; file.index < net->dev.nvqs; ++file.index) {
> const VhostOps *vhost_ops = net->dev.vhost_ops;
> - int r = vhost_ops->vhost_call(&net->dev, VHOST_RESET_OWNER,
> - NULL);
> + int r = vhost_ops->vhost_reset_owner(&net->dev);
> assert(r >= 0);
> }
> }
> diff --git a/hw/scsi/vhost-scsi.c b/hw/scsi/vhost-scsi.c
> index bac9ddb..a0034ab 100644
> --- a/hw/scsi/vhost-scsi.c
> +++ b/hw/scsi/vhost-scsi.c
> @@ -45,7 +45,7 @@ static int vhost_scsi_set_endpoint(VHostSCSI *s)
>
> memset(&backend, 0, sizeof(backend));
> pstrcpy(backend.vhost_wwpn, sizeof(backend.vhost_wwpn), vs->conf.wwpn);
> - ret = vhost_ops->vhost_call(&s->dev, VHOST_SCSI_SET_ENDPOINT, &backend);
> + ret = vhost_ops->vhost_scsi_set_endpoint(&s->dev, &backend);
> if (ret < 0) {
> return -errno;
> }
> @@ -60,7 +60,7 @@ static void vhost_scsi_clear_endpoint(VHostSCSI *s)
>
> memset(&backend, 0, sizeof(backend));
> pstrcpy(backend.vhost_wwpn, sizeof(backend.vhost_wwpn), vs->conf.wwpn);
> - vhost_ops->vhost_call(&s->dev, VHOST_SCSI_CLEAR_ENDPOINT, &backend);
> + vhost_ops->vhost_scsi_clear_endpoint(&s->dev, &backend);
> }
>
> static int vhost_scsi_start(VHostSCSI *s)
> @@ -76,8 +76,7 @@ static int vhost_scsi_start(VHostSCSI *s)
> return -ENOSYS;
> }
>
> - ret = vhost_ops->vhost_call(&s->dev,
> - VHOST_SCSI_GET_ABI_VERSION, &abi_version);
> + ret = vhost_ops->vhost_scsi_get_abi_version(&s->dev, &abi_version);
> if (ret < 0) {
> return -errno;
> }
> diff --git a/hw/virtio/vhost-backend.c b/hw/virtio/vhost-backend.c
> index 4d68a27..bf2d1d4 100644
> --- a/hw/virtio/vhost-backend.c
> +++ b/hw/virtio/vhost-backend.c
> @@ -11,19 +11,10 @@
> #include "hw/virtio/vhost.h"
> #include "hw/virtio/vhost-backend.h"
> #include "qemu/error-report.h"
> +#include "linux/vhost.h"
>
> #include <sys/ioctl.h>
>
> -static int vhost_kernel_call(struct vhost_dev *dev, unsigned long int
> request,
> - void *arg)
> -{
> - int fd = (uintptr_t) dev->opaque;
> -
> - assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_KERNEL);
> -
> - return ioctl(fd, request, arg);
> -}
> -
> static int vhost_kernel_init(struct vhost_dev *dev, void *opaque)
> {
> assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_KERNEL);
> @@ -42,11 +33,136 @@ static int vhost_kernel_cleanup(struct vhost_dev *dev)
> return close(fd);
> }
>
> +static int vhost_kernel_call(struct vhost_dev *dev,
> + unsigned long int request, void *arg)
> +{
> + int fd = (uintptr_t) dev->opaque;
> +
> + assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_KERNEL);
> +
> + return ioctl(fd, request, arg);
> +}
> +
> +static int vhost_net_set_backend(struct vhost_dev *dev,
> + struct vhost_vring_file *file)
> +{
> + return vhost_kernel_call(dev, VHOST_NET_SET_BACKEND, file);
> +}
> +
> +static int vhost_scsi_set_endpoint(struct vhost_dev *dev,
> + struct vhost_scsi_target *target)
> +{
> + return vhost_kernel_call(dev, VHOST_SCSI_SET_ENDPOINT, target);
> +}
> +
> +static int vhost_scsi_clear_endpoint(struct vhost_dev *dev,
> + struct vhost_scsi_target *target)
> +{
> + return vhost_kernel_call(dev, VHOST_SCSI_CLEAR_ENDPOINT, target);
> +}
> +
> +static int vhost_scsi_get_abi_version(struct vhost_dev *dev, int *version)
> +{
> + return vhost_kernel_call(dev, VHOST_SCSI_GET_ABI_VERSION, version);
> +}
> +
> +static int vhost_set_log_base(struct vhost_dev *dev, uint64_t base)
> +{
> + return vhost_kernel_call(dev, VHOST_SET_LOG_BASE, &base);
> +}
> +
> +static int vhost_set_mem_table(struct vhost_dev *dev,
> + struct vhost_memory *mem)
> +{
> + return vhost_kernel_call(dev, VHOST_SET_MEM_TABLE, mem);
> +}
> +
> +static int vhost_set_vring_addr(struct vhost_dev *dev,
> + struct vhost_vring_addr *addr)
> +{
> + return vhost_kernel_call(dev, VHOST_SET_VRING_ADDR, addr);
> +}
> +
> +static int vhost_set_vring_endian(struct vhost_dev *dev,
> + struct vhost_vring_state *ring)
> +{
> + return vhost_kernel_call(dev, VHOST_SET_VRING_ENDIAN, ring);
> +}
> +
> +static int vhost_set_vring_num(struct vhost_dev *dev,
> + struct vhost_vring_state *ring)
> +{
> + return vhost_kernel_call(dev, VHOST_SET_VRING_NUM, ring);
> +}
> +
> +static int vhost_set_vring_base(struct vhost_dev *dev,
> + struct vhost_vring_state *ring)
> +{
> + return vhost_kernel_call(dev, VHOST_SET_VRING_BASE, ring);
> +}
> +
> +static int vhost_get_vring_base(struct vhost_dev *dev,
> + struct vhost_vring_state *ring)
> +{
> + return vhost_kernel_call(dev, VHOST_GET_VRING_BASE, ring);
> +}
> +
> +static int vhost_set_vring_kick(struct vhost_dev *dev,
> + struct vhost_vring_file *file)
> +{
> + return vhost_kernel_call(dev, VHOST_SET_VRING_KICK, file);
> +}
> +
> +static int vhost_set_vring_call(struct vhost_dev *dev,
> + struct vhost_vring_file *file)
> +{
> + return vhost_kernel_call(dev, VHOST_SET_VRING_CALL, file);
> +}
> +
> +static int vhost_set_features(struct vhost_dev *dev,
> + uint64_t features)
> +{
> + return vhost_kernel_call(dev, VHOST_SET_FEATURES, &features);
> +}
> +
> +static int vhost_kernel_get_features(struct vhost_dev *dev,
> + uint64_t *features)
> +{
> + return vhost_kernel_call(dev, VHOST_GET_FEATURES, features);
> +}
> +
> +static int vhost_set_owner(struct vhost_dev *dev)
> +{
> + return vhost_kernel_call(dev, VHOST_SET_OWNER, NULL);
> +}
> +
> +static int vhost_reset_owner(struct vhost_dev *dev)
> +{
> + return vhost_kernel_call(dev, VHOST_RESET_OWNER, NULL);
> +}
> +
> static const VhostOps kernel_ops = {
> .backend_type = VHOST_BACKEND_TYPE_KERNEL,
> - .vhost_call = vhost_kernel_call,
> .vhost_backend_init = vhost_kernel_init,
> - .vhost_backend_cleanup = vhost_kernel_cleanup
> + .vhost_backend_cleanup = vhost_kernel_cleanup,
> +
> + .vhost_net_set_backend = vhost_net_set_backend,
> + .vhost_scsi_set_endpoint = vhost_scsi_set_endpoint,
> + .vhost_scsi_clear_endpoint = vhost_scsi_clear_endpoint,
> + .vhost_scsi_get_abi_version = vhost_scsi_get_abi_version,
> + .vhost_set_log_base = vhost_set_log_base,
> + .vhost_set_mem_table = vhost_set_mem_table,
> + .vhost_set_vring_addr = vhost_set_vring_addr,
> + .vhost_set_vring_endian = vhost_set_vring_endian,
> + .vhost_set_vring_num = vhost_set_vring_num,
> + .vhost_set_vring_base = vhost_set_vring_base,
> + .vhost_get_vring_base = vhost_get_vring_base,
> + .vhost_set_vring_kick = vhost_set_vring_kick,
> + .vhost_set_vring_call = vhost_set_vring_call,
> + .vhost_set_features = vhost_set_features,
> + .vhost_get_features = vhost_kernel_get_features,
> + .vhost_set_owner = vhost_set_owner,
> + .vhost_reset_owner = vhost_reset_owner,
> };
>
> int vhost_set_backend_type(struct vhost_dev *dev, VhostBackendType
> backend_type)
> diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
> index de87562..d5b7951 100644
> --- a/hw/virtio/vhost-user.c
> +++ b/hw/virtio/vhost-user.c
> @@ -176,6 +176,7 @@ fail:
> return -1;
> }
>
> +/* most non-init callers ignore the error */
> static int vhost_user_write(struct vhost_dev *dev, VhostUserMsg *msg,
> int *fds, int fd_num)
> {
> @@ -190,148 +191,280 @@ static int vhost_user_write(struct vhost_dev *dev,
> VhostUserMsg *msg,
> 0 : -1;
> }
>
> -static int vhost_user_call(struct vhost_dev *dev, unsigned long int request,
> - void *arg)
> +static int vhost_net_set_backend(struct vhost_dev *dev,
> + struct vhost_vring_file *file)
> +{
> + error_report("vhost-user trying to send unhandled ioctl");
> + return -1;
> +}
> +
> +static int vhost_scsi_set_endpoint(struct vhost_dev *dev,
> + struct vhost_scsi_target *target)
> +{
> + error_report("vhost-user trying to send unhandled ioctl");
> + return -1;
> +}
> +
> +static int vhost_scsi_clear_endpoint(struct vhost_dev *dev,
> + struct vhost_scsi_target *target)
> +{
> + error_report("vhost-user trying to send unhandled ioctl");
> + return -1;
> +}
> +
> +static int vhost_scsi_get_abi_version(struct vhost_dev *dev, int *version)
> +{
> + error_report("vhost-user trying to send unhandled ioctl");
> + return -1;
> +}
> +
> +static int vhost_set_log_base(struct vhost_dev *dev, uint64_t base)
> +{
> + VhostUserMsg msg = {
> + .request = VHOST_USER_SET_LOG_BASE,
> + .flags = VHOST_USER_VERSION,
> + .u64 = base,
> + .size = sizeof(m.u64),
> + };
> +
> + vhost_user_write(dev, &msg, NULL, 0);
> +
> + return 0;
> +}
> +
> +static int vhost_set_mem_table(struct vhost_dev *dev,
> + struct vhost_memory *mem)
> {
> - VhostUserMsg msg;
> - VhostUserRequest msg_request;
> - struct vhost_vring_file *file = 0;
> - int need_reply = 0;
> int fds[VHOST_MEMORY_MAX_NREGIONS];
> int i, fd;
> size_t fd_num = 0;
> + VhostUserMsg msg = {
> + .request = VHOST_USER_SET_MEM_TABLE,
> + .flags = VHOST_USER_VERSION,
> + };
>
> - assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_USER);
> + for (i = 0; i < dev->mem->nregions; ++i) {
> + struct vhost_memory_region *reg = dev->mem->regions + i;
> + ram_addr_t ram_addr;
> +
> + assert((uintptr_t)reg->userspace_addr == reg->userspace_addr);
> + qemu_ram_addr_from_host((void *)(uintptr_t)reg->userspace_addr,
> + &ram_addr);
> + fd = qemu_get_ram_fd(ram_addr);
> + if (fd > 0) {
> + msg.memory.regions[fd_num].userspace_addr = reg->userspace_addr;
> + msg.memory.regions[fd_num].memory_size = reg->memory_size;
> + msg.memory.regions[fd_num].guest_phys_addr =
> reg->guest_phys_addr;
> + msg.memory.regions[fd_num].mmap_offset = reg->userspace_addr -
> + (uintptr_t) qemu_get_ram_block_host_ptr(ram_addr);
> + assert(fd_num < VHOST_MEMORY_MAX_NREGIONS);
> + fds[fd_num++] = fd;
> + }
> + }
>
> - msg_request = vhost_user_request_translate(request);
> - msg.request = msg_request;
> - msg.flags = VHOST_USER_VERSION;
> - msg.size = 0;
> + msg.memory.nregions = fd_num;
>
> - switch (msg_request) {
> - case VHOST_USER_GET_FEATURES:
> - need_reply = 1;
> - break;
> -
> - case VHOST_USER_SET_FEATURES:
> - case VHOST_USER_SET_LOG_BASE:
> - msg.u64 = *((__u64 *) arg);
> - msg.size = sizeof(m.u64);
> - break;
> -
> - case VHOST_USER_SET_OWNER:
> - case VHOST_USER_RESET_OWNER:
> - break;
> -
> - case VHOST_USER_SET_MEM_TABLE:
> - for (i = 0; i < dev->mem->nregions; ++i) {
> - struct vhost_memory_region *reg = dev->mem->regions + i;
> - ram_addr_t ram_addr;
> -
> - assert((uintptr_t)reg->userspace_addr == reg->userspace_addr);
> - qemu_ram_addr_from_host((void *)(uintptr_t)reg->userspace_addr,
> &ram_addr);
> - fd = qemu_get_ram_fd(ram_addr);
> - if (fd > 0) {
> - msg.memory.regions[fd_num].userspace_addr =
> reg->userspace_addr;
> - msg.memory.regions[fd_num].memory_size = reg->memory_size;
> - msg.memory.regions[fd_num].guest_phys_addr =
> reg->guest_phys_addr;
> - msg.memory.regions[fd_num].mmap_offset = reg->userspace_addr
> -
> - (uintptr_t) qemu_get_ram_block_host_ptr(ram_addr);
> - assert(fd_num < VHOST_MEMORY_MAX_NREGIONS);
> - fds[fd_num++] = fd;
> - }
> - }
> + if (!fd_num) {
> + error_report("Failed initializing vhost-user memory map, "
> + "consider using -object memory-backend-file share=on");
> + return -1;
> + }
>
> - msg.memory.nregions = fd_num;
> + msg.size = sizeof(m.memory.nregions);
> + msg.size += sizeof(m.memory.padding);
> + msg.size += fd_num * sizeof(VhostUserMemoryRegion);
>
> - if (!fd_num) {
> - error_report("Failed initializing vhost-user memory map, "
> - "consider using -object memory-backend-file share=on");
> - return -1;
> - }
> + vhost_user_write(dev, &msg, fds, fd_num);
>
> - msg.size = sizeof(m.memory.nregions);
> - msg.size += sizeof(m.memory.padding);
> - msg.size += fd_num * sizeof(VhostUserMemoryRegion);
> -
> - break;
> -
> - case VHOST_USER_SET_LOG_FD:
> - fds[fd_num++] = *((int *) arg);
> - break;
> -
> - case VHOST_USER_SET_VRING_NUM:
> - case VHOST_USER_SET_VRING_BASE:
> - memcpy(&msg.state, arg, sizeof(struct vhost_vring_state));
> - msg.size = sizeof(m.state);
> - break;
> -
> - case VHOST_USER_GET_VRING_BASE:
> - memcpy(&msg.state, arg, sizeof(struct vhost_vring_state));
> - msg.size = sizeof(m.state);
> - need_reply = 1;
> - break;
> -
> - case VHOST_USER_SET_VRING_ADDR:
> - memcpy(&msg.addr, arg, sizeof(struct vhost_vring_addr));
> - msg.size = sizeof(m.addr);
> - break;
> -
> - case VHOST_USER_SET_VRING_KICK:
> - case VHOST_USER_SET_VRING_CALL:
> - case VHOST_USER_SET_VRING_ERR:
> - file = arg;
> - msg.u64 = file->index & VHOST_USER_VRING_IDX_MASK;
> - msg.size = sizeof(m.u64);
> - if (ioeventfd_enabled() && file->fd > 0) {
> - fds[fd_num++] = file->fd;
> - } else {
> - msg.u64 |= VHOST_USER_VRING_NOFD_MASK;
> - }
> - break;
> - default:
> - error_report("vhost-user trying to send unhandled ioctl");
> + return 0;
> +}
> +
> +static int vhost_set_vring_addr(struct vhost_dev *dev,
> + struct vhost_vring_addr *addr)
> +{
> + VhostUserMsg msg = {
> + .request = VHOST_USER_SET_VRING_ADDR,
> + .flags = VHOST_USER_VERSION,
> + .addr = *addr,
> + .size = sizeof(*addr),
> + };
> +
> + vhost_user_write(dev, &msg, NULL, 0);
> +
> + return 0;
> +}
> +
> +static int vhost_set_vring_endian(struct vhost_dev *dev,
> + struct vhost_vring_state *ring)
> +{
> + error_report("vhost-user trying to send unhandled ioctl");
> + return -1;
> +}
> +
> +static int vhost_set_vring_num(struct vhost_dev *dev,
> + struct vhost_vring_state *ring)
> +{
> + VhostUserMsg msg = {
> + .request = VHOST_USER_SET_VRING_NUM,
> + .flags = VHOST_USER_VERSION,
> + .state = *ring,
> + .size = sizeof(*ring),
> + };
> +
> + vhost_user_write(dev, &msg, NULL, 0);
> +
> + return 0;
> +}
> +
> +static int vhost_set_vring_base(struct vhost_dev *dev,
> + struct vhost_vring_state *ring)
> +{
> + VhostUserMsg msg = {
> + .request = VHOST_USER_SET_VRING_BASE,
> + .flags = VHOST_USER_VERSION,
> + .state = *ring,
> + .size = sizeof(*ring),
> + };
> +
> + vhost_user_write(dev, &msg, NULL, 0);
> +
> + return 0;
> +}
> +
> +static int vhost_get_vring_base(struct vhost_dev *dev,
> + struct vhost_vring_state *ring)
> +{
> + VhostUserMsg msg = {
> + .request = VHOST_USER_GET_VRING_BASE,
> + .flags = VHOST_USER_VERSION,
> + .state = *ring,
> + .size = sizeof(*ring),
> + };
> +
> + vhost_user_write(dev, &msg, NULL, 0);
> +
> + if (vhost_user_read(dev, &msg) < 0) {
> + return 0;
> + }
> +
> + if (msg.request != VHOST_USER_GET_VRING_BASE) {
> + error_report("Received unexpected msg type. Expected %d received %d",
> + VHOST_USER_GET_FEATURES, msg.request);
> return -1;
> - break;
> }
>
> - if (vhost_user_write(dev, &msg, fds, fd_num) < 0) {
> - return 0;
> + if (msg.size != sizeof(m.state)) {
> + error_report("Received bad msg size.");
> + return -1;
> }
>
> - if (need_reply) {
> - if (vhost_user_read(dev, &msg) < 0) {
> - return 0;
> - }
> + *ring = msg.state;
>
> - if (msg_request != msg.request) {
> - error_report("Received unexpected msg type."
> - " Expected %d received %d", msg_request, msg.request);
> - return -1;
> - }
> + return 0;
> +}
>
> - switch (msg_request) {
> - case VHOST_USER_GET_FEATURES:
> - if (msg.size != sizeof(m.u64)) {
> - error_report("Received bad msg size.");
> - return -1;
> - }
> - *((__u64 *) arg) = msg.u64;
> - break;
> - case VHOST_USER_GET_VRING_BASE:
> - if (msg.size != sizeof(m.state)) {
> - error_report("Received bad msg size.");
> - return -1;
> - }
> - memcpy(arg, &msg.state, sizeof(struct vhost_vring_state));
> - break;
> - default:
> - error_report("Received unexpected msg type.");
> - return -1;
> - break;
> - }
> +static int vhost_set_vring_file(struct vhost_dev *dev,
> + VhostUserRequest request,
> + struct vhost_vring_file *file)
> +{
> + int fds[VHOST_MEMORY_MAX_NREGIONS];
> + size_t fd_num = 0;
> + VhostUserMsg msg = {
> + .request = request,
> + .flags = VHOST_USER_VERSION,
> + .u64 = file->index & VHOST_USER_VRING_IDX_MASK,
> + .size = sizeof(m.u64),
> + };
> +
> + if (ioeventfd_enabled() && file->fd > 0) {
> + fds[fd_num++] = file->fd;
> + } else {
> + msg.u64 |= VHOST_USER_VRING_NOFD_MASK;
> }
>
> + vhost_user_write(dev, &msg, fds, fd_num);
> +
> + return 0;
> +}
> +
> +static int vhost_set_vring_kick(struct vhost_dev *dev,
> + struct vhost_vring_file *file)
> +{
> + return vhost_set_vring_file(dev, VHOST_USER_SET_VRING_KICK, file);
> +}
> +
> +static int vhost_set_vring_call(struct vhost_dev *dev,
> + struct vhost_vring_file *file)
> +{
> + return vhost_set_vring_file(dev, VHOST_USER_SET_VRING_CALL, file);
> +}
> +
> +static int vhost_set_features(struct vhost_dev *dev,
> + uint64_t features)
> +{
> + VhostUserMsg msg = {
> + .request = VHOST_USER_SET_FEATURES,
> + .flags = VHOST_USER_VERSION,
> + .u64 = features,
> + .size = sizeof(m.u64),
> + };
> +
> + vhost_user_write(dev, &msg, NULL, 0);
> +
> + return 0;
> +}
> +
> +static int vhost_user_get_features(struct vhost_dev *dev,
> + uint64_t *features)
> +{
> + VhostUserMsg msg = {
> + .request = VHOST_USER_GET_FEATURES,
> + .flags = VHOST_USER_VERSION,
> + };
> +
> + vhost_user_write(dev, &msg, NULL, 0);
> +
> + if (vhost_user_read(dev, &msg) < 0) {
> + return 0;
> + }
> +
> + if (msg.request != VHOST_USER_GET_FEATURES) {
> + error_report("Received unexpected msg type. Expected %d received %d",
> + VHOST_USER_GET_FEATURES, msg.request);
> + return -1;
> + }
> +
> + if (msg.size != sizeof(m.u64)) {
> + error_report("Received bad msg size.");
> + return -1;
> + }
> +
> + *features = msg.u64;
> +
> + return 0;
> +}
> +
> +static int vhost_set_owner(struct vhost_dev *dev)
> +{
> + VhostUserMsg msg = {
> + .request = VHOST_USER_SET_OWNER,
> + .flags = VHOST_USER_VERSION,
> + };
> +
> + vhost_user_write(dev, &msg, NULL, 0);
> +
> + return 0;
> +}
> +
> +static int vhost_reset_owner(struct vhost_dev *dev)
> +{
> + VhostUserMsg msg = {
> + .request = VHOST_USER_RESET_OWNER,
> + .flags = VHOST_USER_VERSION,
> + };
> +
> + vhost_user_write(dev, &msg, NULL, 0);
> +
> return 0;
> }
>
If you define a specific function for each messages it can be
interesting to add function for messages to get/set protocol features
(VHOST_USER_GET_PROTOCOL_FEATURES and
VHOST_USER_SET_PROTOCOL_FEATURES) and modify the vhost_user_init
function to call these specific functions (this function can be
already modified to use the specific function for
VHOST_USER_GET_FEATURES message to avoid code duplication)
> @@ -402,7 +535,24 @@ static int vhost_user_cleanup(struct vhost_dev *dev)
>
> const VhostOps user_ops = {
> .backend_type = VHOST_BACKEND_TYPE_USER,
> - .vhost_call = vhost_user_call,
> .vhost_backend_init = vhost_user_init,
> - .vhost_backend_cleanup = vhost_user_cleanup
> - };
> + .vhost_backend_cleanup = vhost_user_cleanup,
> +
> + .vhost_net_set_backend = vhost_net_set_backend,
> + .vhost_scsi_set_endpoint = vhost_scsi_set_endpoint,
> + .vhost_scsi_clear_endpoint = vhost_scsi_clear_endpoint,
> + .vhost_scsi_get_abi_version = vhost_scsi_get_abi_version,
> + .vhost_set_log_base = vhost_set_log_base,
> + .vhost_set_mem_table = vhost_set_mem_table,
> + .vhost_set_vring_addr = vhost_set_vring_addr,
> + .vhost_set_vring_endian = vhost_set_vring_endian,
> + .vhost_set_vring_num = vhost_set_vring_num,
> + .vhost_set_vring_base = vhost_set_vring_base,
> + .vhost_get_vring_base = vhost_get_vring_base,
> + .vhost_set_vring_kick = vhost_set_vring_kick,
> + .vhost_set_vring_call = vhost_set_vring_call,
> + .vhost_set_features = vhost_set_features,
> + .vhost_get_features = vhost_user_get_features,
> + .vhost_set_owner = vhost_set_owner,
> + .vhost_reset_owner = vhost_reset_owner,
> +};
> diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
> index 81209ba..83ef164 100644
> --- a/hw/virtio/vhost.c
> +++ b/hw/virtio/vhost.c
> @@ -359,7 +359,7 @@ static inline void vhost_dev_log_resize(struct vhost_dev*
> dev, uint64_t size)
>
> /* inform backend of log switching, this must be done before
> releasing the current log, to ensure no logging is lost */
> - r = dev->vhost_ops->vhost_call(dev, VHOST_SET_LOG_BASE, &log_base);
> + r = dev->vhost_ops->vhost_set_log_base(dev, log_base);
> assert(r >= 0);
> vhost_log_put(dev, true);
> dev->log = log;
> @@ -525,7 +525,7 @@ static void vhost_commit(MemoryListener *listener)
> }
>
> if (!dev->log_enabled) {
> - r = dev->vhost_ops->vhost_call(dev, VHOST_SET_MEM_TABLE, dev->mem);
> + r = dev->vhost_ops->vhost_set_mem_table(dev, dev->mem);
> assert(r >= 0);
> dev->memory_changed = false;
> return;
> @@ -538,7 +538,7 @@ static void vhost_commit(MemoryListener *listener)
> if (dev->log_size < log_size) {
> vhost_dev_log_resize(dev, log_size + VHOST_LOG_BUFFER);
> }
> - r = dev->vhost_ops->vhost_call(dev, VHOST_SET_MEM_TABLE, dev->mem);
> + r = dev->vhost_ops->vhost_set_mem_table(dev, dev->mem);
> assert(r >= 0);
> /* To log less, can only decrease log size after table update. */
> if (dev->log_size > log_size + VHOST_LOG_BUFFER) {
> @@ -606,7 +606,7 @@ static int vhost_virtqueue_set_addr(struct vhost_dev *dev,
> .log_guest_addr = vq->used_phys,
> .flags = enable_log ? (1 << VHOST_VRING_F_LOG) : 0,
> };
> - int r = dev->vhost_ops->vhost_call(dev, VHOST_SET_VRING_ADDR, &addr);
> + int r = dev->vhost_ops->vhost_set_vring_addr(dev, &addr);
> if (r < 0) {
> return -errno;
> }
> @@ -620,7 +620,7 @@ static int vhost_dev_set_features(struct vhost_dev *dev,
> bool enable_log)
> if (enable_log) {
> features |= 0x1ULL << VHOST_F_LOG_ALL;
> }
> - r = dev->vhost_ops->vhost_call(dev, VHOST_SET_FEATURES, &features);
> + r = dev->vhost_ops->vhost_set_features(dev, features);
> return r < 0 ? -errno : 0;
> }
>
> @@ -725,7 +725,7 @@ static int vhost_virtqueue_set_vring_endian_legacy(struct
> vhost_dev *dev,
> .num = is_big_endian
> };
>
> - if (!dev->vhost_ops->vhost_call(dev, VHOST_SET_VRING_ENDIAN, &s)) {
> + if (!dev->vhost_ops->vhost_set_vring_endian(dev, &s)) {
> return 0;
> }
>
> @@ -756,13 +756,13 @@ static int vhost_virtqueue_start(struct vhost_dev *dev,
> assert(idx >= dev->vq_index && idx < dev->vq_index + dev->nvqs);
>
> vq->num = state.num = virtio_queue_get_num(vdev, idx);
> - r = dev->vhost_ops->vhost_call(dev, VHOST_SET_VRING_NUM, &state);
> + r = dev->vhost_ops->vhost_set_vring_num(dev, &state);
> if (r) {
> return -errno;
> }
>
> state.num = virtio_queue_get_last_avail_idx(vdev, idx);
> - r = dev->vhost_ops->vhost_call(dev, VHOST_SET_VRING_BASE, &state);
> + r = dev->vhost_ops->vhost_set_vring_base(dev, &state);
> if (r) {
> return -errno;
> }
> @@ -814,7 +814,7 @@ static int vhost_virtqueue_start(struct vhost_dev *dev,
> }
>
> file.fd = event_notifier_get_fd(virtio_queue_get_host_notifier(vvq));
> - r = dev->vhost_ops->vhost_call(dev, VHOST_SET_VRING_KICK, &file);
> + r = dev->vhost_ops->vhost_set_vring_kick(dev, &file);
> if (r) {
> r = -errno;
> goto fail_kick;
> @@ -853,7 +853,7 @@ static void vhost_virtqueue_stop(struct vhost_dev *dev,
> };
> int r;
> assert(idx >= dev->vq_index && idx < dev->vq_index + dev->nvqs);
> - r = dev->vhost_ops->vhost_call(dev, VHOST_GET_VRING_BASE, &state);
> + r = dev->vhost_ops->vhost_get_vring_base(dev, &state);
> if (r < 0) {
> fprintf(stderr, "vhost VQ %d ring restore failed: %d\n", idx, r);
> fflush(stderr);
> @@ -909,7 +909,7 @@ static int vhost_virtqueue_init(struct vhost_dev *dev,
> }
>
> file.fd = event_notifier_get_fd(&vq->masked_notifier);
> - r = dev->vhost_ops->vhost_call(dev, VHOST_SET_VRING_CALL, &file);
> + r = dev->vhost_ops->vhost_set_vring_call(dev, &file);
> if (r) {
> r = -errno;
> goto fail_call;
> @@ -941,12 +941,12 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
> return -errno;
> }
>
> - r = hdev->vhost_ops->vhost_call(hdev, VHOST_SET_OWNER, NULL);
> + r = hdev->vhost_ops->vhost_set_owner(hdev);
> if (r < 0) {
> goto fail;
> }
>
> - r = hdev->vhost_ops->vhost_call(hdev, VHOST_GET_FEATURES, &features);
> + r = hdev->vhost_ops->vhost_get_features(hdev, &features);
> if (r < 0) {
> goto fail;
> }
> @@ -1102,7 +1102,7 @@ void vhost_virtqueue_mask(struct vhost_dev *hdev,
> VirtIODevice *vdev, int n,
> } else {
> file.fd =
> event_notifier_get_fd(virtio_queue_get_guest_notifier(vvq));
> }
> - r = hdev->vhost_ops->vhost_call(hdev, VHOST_SET_VRING_CALL, &file);
> + r = hdev->vhost_ops->vhost_set_vring_call(hdev, &file);
> assert(r >= 0);
> }
>
> @@ -1144,7 +1144,7 @@ int vhost_dev_start(struct vhost_dev *hdev,
> VirtIODevice *vdev)
> if (r < 0) {
> goto fail_features;
> }
> - r = hdev->vhost_ops->vhost_call(hdev, VHOST_SET_MEM_TABLE, hdev->mem);
> + r = hdev->vhost_ops->vhost_set_mem_table(hdev, hdev->mem);
> if (r < 0) {
> r = -errno;
> goto fail_mem;
> @@ -1166,8 +1166,8 @@ int vhost_dev_start(struct vhost_dev *hdev,
> VirtIODevice *vdev)
> hdev->log_size = vhost_get_log_size(hdev);
> hdev->log = vhost_log_get(hdev->log_size, share);
> log_base = (uintptr_t)hdev->log->log;
> - r = hdev->vhost_ops->vhost_call(hdev, VHOST_SET_LOG_BASE,
> - hdev->log_size ? &log_base : NULL);
> + r = hdev->vhost_ops->vhost_set_log_base(hdev,
> + hdev->log_size ? log_base :
> 0);
> if (r < 0) {
> r = -errno;
> goto fail_log;
> diff --git a/include/hw/virtio/vhost-backend.h
> b/include/hw/virtio/vhost-backend.h
> index e472f29..42cfb87 100644
> --- a/include/hw/virtio/vhost-backend.h
> +++ b/include/hw/virtio/vhost-backend.h
> @@ -19,17 +19,70 @@ typedef enum VhostBackendType {
> } VhostBackendType;
>
> struct vhost_dev;
> +struct vhost_memory;
> +struct vhost_vring_file;
> +struct vhost_vring_state;
> +struct vhost_vring_addr;
> +struct vhost_scsi_target;
>
> -typedef int (*vhost_call)(struct vhost_dev *dev, unsigned long int request,
> - void *arg);
> typedef int (*vhost_backend_init)(struct vhost_dev *dev, void *opaque);
> typedef int (*vhost_backend_cleanup)(struct vhost_dev *dev);
>
> +typedef int (*vhost_net_set_backend_op)(struct vhost_dev *dev,
> + struct vhost_vring_file *file);
> +typedef int (*vhost_scsi_set_endpoint_op)(struct vhost_dev *dev,
> + struct vhost_scsi_target *target);
> +typedef int (*vhost_scsi_clear_endpoint_op)(struct vhost_dev *dev,
> + struct vhost_scsi_target
> *target);
> +typedef int (*vhost_scsi_get_abi_version_op)(struct vhost_dev *dev,
> + int *version);
> +typedef int (*vhost_set_log_base_op)(struct vhost_dev *dev, uint64_t base);
> +typedef int (*vhost_set_mem_table_op)(struct vhost_dev *dev,
> + struct vhost_memory *mem);
> +typedef int (*vhost_set_vring_addr_op)(struct vhost_dev *dev,
> + struct vhost_vring_addr *addr);
> +typedef int (*vhost_set_vring_endian_op)(struct vhost_dev *dev,
> + struct vhost_vring_state *ring);
> +typedef int (*vhost_set_vring_num_op)(struct vhost_dev *dev,
> + struct vhost_vring_state *ring);
> +typedef int (*vhost_set_vring_base_op)(struct vhost_dev *dev,
> + struct vhost_vring_state *ring);
> +typedef int (*vhost_get_vring_base_op)(struct vhost_dev *dev,
> + struct vhost_vring_state *ring);
> +typedef int (*vhost_set_vring_kick_op)(struct vhost_dev *dev,
> + struct vhost_vring_file *file);
> +typedef int (*vhost_set_vring_call_op)(struct vhost_dev *dev,
> + struct vhost_vring_file *file);
> +typedef int (*vhost_set_features_op)(struct vhost_dev *dev,
> + uint64_t features);
> +typedef int (*vhost_get_features_op)(struct vhost_dev *dev,
> + uint64_t *features);
> +typedef int (*vhost_set_owner_op)(struct vhost_dev *dev);
> +typedef int (*vhost_reset_owner_op)(struct vhost_dev *dev);
> +
> typedef struct VhostOps {
> VhostBackendType backend_type;
> - vhost_call vhost_call;
> +
> vhost_backend_init vhost_backend_init;
> vhost_backend_cleanup vhost_backend_cleanup;
> +
> + vhost_net_set_backend_op vhost_net_set_backend;
> + vhost_scsi_set_endpoint_op vhost_scsi_set_endpoint;
> + vhost_scsi_clear_endpoint_op vhost_scsi_clear_endpoint;
> + vhost_scsi_get_abi_version_op vhost_scsi_get_abi_version;
> + vhost_set_log_base_op vhost_set_log_base;
> + vhost_set_mem_table_op vhost_set_mem_table;
> + vhost_set_vring_addr_op vhost_set_vring_addr;
> + vhost_set_vring_endian_op vhost_set_vring_endian;
> + vhost_set_vring_num_op vhost_set_vring_num;
> + vhost_set_vring_base_op vhost_set_vring_base;
> + vhost_get_vring_base_op vhost_get_vring_base;
> + vhost_set_vring_kick_op vhost_set_vring_kick;
> + vhost_set_vring_call_op vhost_set_vring_call;
> + vhost_set_features_op vhost_set_features;
> + vhost_get_features_op vhost_get_features;
> + vhost_set_owner_op vhost_set_owner;
> + vhost_reset_owner_op vhost_reset_owner;
> } VhostOps;
>
> extern const VhostOps user_ops;
> --
> 2.4.3
>
- [Qemu-devel] [PATCH v4 03/22] vhost-user: unit test for new messages, (continued)
- [Qemu-devel] [PATCH v4 03/22] vhost-user: unit test for new messages, marcandre . lureau, 2015/09/19
- [Qemu-devel] [PATCH v4 04/22] configure: probe for memfd, marcandre . lureau, 2015/09/19
- [Qemu-devel] [PATCH v4 05/22] util: add linux-only memfd fallback, marcandre . lureau, 2015/09/19
- [Qemu-devel] [PATCH v4 06/22] util: add memfd helpers, marcandre . lureau, 2015/09/19
- [Qemu-devel] [PATCH v4 07/22] vhost: alloc shareable log, marcandre . lureau, 2015/09/19
- [Qemu-devel] [PATCH v4 08/22] vhost: document log resizing, marcandre . lureau, 2015/09/19
- [Qemu-devel] [PATCH v4 09/22] vhost: use a function for each call, marcandre . lureau, 2015/09/19
- [Qemu-devel] [PATCH v4 10/22] vhost-user: remove vhost_user_request_translate(), marcandre . lureau, 2015/09/19
- [Qemu-devel] [PATCH v4 11/22] vhost-user: send log shm fd along with log_base, marcandre . lureau, 2015/09/19
[Qemu-devel] [PATCH v4 12/22] vhost: only use shared log if in use by backend, marcandre . lureau, 2015/09/19