From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:43700) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Zdww0-0007GD-Vw for qemu-devel@nongnu.org; Mon, 21 Sep 2015 04:58:56 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Zdwvv-0008He-Ja for qemu-devel@nongnu.org; Mon, 21 Sep 2015 04:58:52 -0400 Received: from mx1.redhat.com ([209.132.183.28]:59018) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Zdwvv-0008HL-5y for qemu-devel@nongnu.org; Mon, 21 Sep 2015 04:58:47 -0400 Date: Mon, 21 Sep 2015 11:58:42 +0300 From: "Michael S. Tsirkin" Message-ID: <20150921115644-mutt-send-email-mst@redhat.com> References: <1442657533-13030-1-git-send-email-marcandre.lureau@redhat.com> <1442657533-13030-10-git-send-email-marcandre.lureau@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Disposition: inline In-Reply-To: <1442657533-13030-10-git-send-email-marcandre.lureau@redhat.com> Content-Transfer-Encoding: quoted-printable Subject: Re: [Qemu-devel] [PATCH v4 09/22] vhost: use a function for each call List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: marcandre.lureau@redhat.com Cc: haifeng.lin@huawei.com, thibaut.collet@6wind.com, jasowang@redhat.com, qemu-devel@nongnu.org, pbonzini@redhat.com On Sat, Sep 19, 2015 at 12:12:00PM +0200, marcandre.lureau@redhat.com wro= te: > From: Marc-Andr=E9 Lureau >=20 > Replace the generic vhost_call() by specific functions for each > function call to help with type safety and changing arguments. >=20 > Signed-off-by: Marc-Andr=E9 Lureau OK but I would rather not make logging feature depend on the refactoring. How about moving each call over from vhost_call by a separate patch? Start with vhost_set_log_base as the 1st one, this way I can apply logging support while we still review the larger refactorings. > --- > 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(-) >=20 > 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 *ne= t, > file.fd =3D net->backend; > for (file.index =3D 0; file.index < net->dev.nvqs; ++file.inde= x) { > const VhostOps *vhost_ops =3D net->dev.vhost_ops; > - r =3D vhost_ops->vhost_call(&net->dev, VHOST_NET_SET_BACKE= ND, > - &file); > + r =3D vhost_ops->vhost_net_set_backend(&net->dev, &file); > if (r < 0) { > r =3D -errno; > goto fail; > @@ -257,8 +256,7 @@ fail: > if (net->nc->info->type =3D=3D NET_CLIENT_OPTIONS_KIND_TAP) { > while (file.index-- > 0) { > const VhostOps *vhost_ops =3D net->dev.vhost_ops; > - int r =3D vhost_ops->vhost_call(&net->dev, VHOST_NET_SET_B= ACKEND, > - &file); > + int r =3D vhost_ops->vhost_net_set_backend(&net->dev, &fil= e); > assert(r >=3D 0); > } > } > @@ -280,15 +278,13 @@ static void vhost_net_stop_one(struct vhost_net *= net, > if (net->nc->info->type =3D=3D NET_CLIENT_OPTIONS_KIND_TAP) { > for (file.index =3D 0; file.index < net->dev.nvqs; ++file.inde= x) { > const VhostOps *vhost_ops =3D net->dev.vhost_ops; > - int r =3D vhost_ops->vhost_call(&net->dev, VHOST_NET_SET_B= ACKEND, > - &file); > + int r =3D vhost_ops->vhost_net_set_backend(&net->dev, &fil= e); > assert(r >=3D 0); > } > } else if (net->nc->info->type =3D=3D NET_CLIENT_OPTIONS_KIND_VHOS= T_USER) { > for (file.index =3D 0; file.index < net->dev.nvqs; ++file.inde= x) { > const VhostOps *vhost_ops =3D net->dev.vhost_ops; > - int r =3D vhost_ops->vhost_call(&net->dev, VHOST_RESET_OWN= ER, > - NULL); > + int r =3D vhost_ops->vhost_reset_owner(&net->dev); > assert(r >=3D 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) > =20 > memset(&backend, 0, sizeof(backend)); > pstrcpy(backend.vhost_wwpn, sizeof(backend.vhost_wwpn), vs->conf.w= wpn); > - ret =3D vhost_ops->vhost_call(&s->dev, VHOST_SCSI_SET_ENDPOINT, &b= ackend); > + ret =3D 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) > =20 > memset(&backend, 0, sizeof(backend)); > pstrcpy(backend.vhost_wwpn, sizeof(backend.vhost_wwpn), vs->conf.w= wpn); > - vhost_ops->vhost_call(&s->dev, VHOST_SCSI_CLEAR_ENDPOINT, &backend= ); > + vhost_ops->vhost_scsi_clear_endpoint(&s->dev, &backend); > } > =20 > static int vhost_scsi_start(VHostSCSI *s) > @@ -76,8 +76,7 @@ static int vhost_scsi_start(VHostSCSI *s) > return -ENOSYS; > } > =20 > - ret =3D vhost_ops->vhost_call(&s->dev, > - VHOST_SCSI_GET_ABI_VERSION, &abi_versi= on); > + ret =3D vhost_ops->vhost_scsi_get_abi_version(&s->dev, &abi_versio= n); > 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" > =20 > #include > =20 > -static int vhost_kernel_call(struct vhost_dev *dev, unsigned long int = request, > - void *arg) > -{ > - int fd =3D (uintptr_t) dev->opaque; > - > - assert(dev->vhost_ops->backend_type =3D=3D VHOST_BACKEND_TYPE_KERN= EL); > - > - return ioctl(fd, request, arg); > -} > - > static int vhost_kernel_init(struct vhost_dev *dev, void *opaque) > { > assert(dev->vhost_ops->backend_type =3D=3D VHOST_BACKEND_TYPE_KERN= EL); > @@ -42,11 +33,136 @@ static int vhost_kernel_cleanup(struct vhost_dev *= dev) > return close(fd); > } > =20 > +static int vhost_kernel_call(struct vhost_dev *dev, > + unsigned long int request, void *arg) > +{ > + int fd =3D (uintptr_t) dev->opaque; > + > + assert(dev->vhost_ops->backend_type =3D=3D VHOST_BACKEND_TYPE_KERN= EL); > + > + 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 *vers= ion) > +{ > + 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 =3D { > .backend_type =3D VHOST_BACKEND_TYPE_KERNEL, > - .vhost_call =3D vhost_kernel_call, > .vhost_backend_init =3D vhost_kernel_init, > - .vhost_backend_cleanup =3D vhost_kernel_cleanup > + .vhost_backend_cleanup =3D vhost_kernel_cleanup, > + > + .vhost_net_set_backend =3D vhost_net_set_backend, > + .vhost_scsi_set_endpoint =3D vhost_scsi_set_endpoint, > + .vhost_scsi_clear_endpoint =3D vhost_scsi_clear_endpoint, > + .vhost_scsi_get_abi_version =3D vhost_scsi_get_abi_version, > + .vhost_set_log_base =3D vhost_set_log_base, > + .vhost_set_mem_table =3D vhost_set_mem_table, > + .vhost_set_vring_addr =3D vhost_set_vring_addr, > + .vhost_set_vring_endian =3D vhost_set_vring_endian, > + .vhost_set_vring_num =3D vhost_set_vring_num, > + .vhost_set_vring_base =3D vhost_set_vring_base, > + .vhost_get_vring_base =3D vhost_get_vring_base, > + .vhost_set_vring_kick =3D vhost_set_vring_kick, > + .vhost_set_vring_call =3D vhost_set_vring_call, > + .vhost_set_features =3D vhost_set_features, > + .vhost_get_features =3D vhost_kernel_get_features, > + .vhost_set_owner =3D vhost_set_owner, > + .vhost_reset_owner =3D vhost_reset_owner, > }; > =20 > int vhost_set_backend_type(struct vhost_dev *dev, VhostBackendType bac= kend_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; > } > =20 > +/* 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 *d= ev, VhostUserMsg *msg, > 0 : -1; > } > =20 > -static int vhost_user_call(struct vhost_dev *dev, unsigned long int re= quest, > - 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 *vers= ion) > +{ > + 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 =3D { > + .request =3D VHOST_USER_SET_LOG_BASE, > + .flags =3D VHOST_USER_VERSION, > + .u64 =3D base, > + .size =3D 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 =3D 0; > - int need_reply =3D 0; > int fds[VHOST_MEMORY_MAX_NREGIONS]; > int i, fd; > size_t fd_num =3D 0; > + VhostUserMsg msg =3D { > + .request =3D VHOST_USER_SET_MEM_TABLE, > + .flags =3D VHOST_USER_VERSION, > + }; > =20 > - assert(dev->vhost_ops->backend_type =3D=3D VHOST_BACKEND_TYPE_USER= ); > + for (i =3D 0; i < dev->mem->nregions; ++i) { > + struct vhost_memory_region *reg =3D dev->mem->regions + i; > + ram_addr_t ram_addr; > + > + assert((uintptr_t)reg->userspace_addr =3D=3D reg->userspace_ad= dr); > + qemu_ram_addr_from_host((void *)(uintptr_t)reg->userspace_addr= , > + &ram_addr); > + fd =3D qemu_get_ram_fd(ram_addr); > + if (fd > 0) { > + msg.memory.regions[fd_num].userspace_addr =3D reg->userspa= ce_addr; > + msg.memory.regions[fd_num].memory_size =3D reg->memory_si= ze; > + msg.memory.regions[fd_num].guest_phys_addr =3D reg->guest_= phys_addr; > + msg.memory.regions[fd_num].mmap_offset =3D reg->userspace_= addr - > + (uintptr_t) qemu_get_ram_block_host_ptr(ram_addr); > + assert(fd_num < VHOST_MEMORY_MAX_NREGIONS); > + fds[fd_num++] =3D fd; > + } > + } > =20 > - msg_request =3D vhost_user_request_translate(request); > - msg.request =3D msg_request; > - msg.flags =3D VHOST_USER_VERSION; > - msg.size =3D 0; > + msg.memory.nregions =3D fd_num; > =20 > - switch (msg_request) { > - case VHOST_USER_GET_FEATURES: > - need_reply =3D 1; > - break; > - > - case VHOST_USER_SET_FEATURES: > - case VHOST_USER_SET_LOG_BASE: > - msg.u64 =3D *((__u64 *) arg); > - msg.size =3D sizeof(m.u64); > - break; > - > - case VHOST_USER_SET_OWNER: > - case VHOST_USER_RESET_OWNER: > - break; > - > - case VHOST_USER_SET_MEM_TABLE: > - for (i =3D 0; i < dev->mem->nregions; ++i) { > - struct vhost_memory_region *reg =3D dev->mem->regions + i; > - ram_addr_t ram_addr; > - > - assert((uintptr_t)reg->userspace_addr =3D=3D reg->userspac= e_addr); > - qemu_ram_addr_from_host((void *)(uintptr_t)reg->userspace_= addr, &ram_addr); > - fd =3D qemu_get_ram_fd(ram_addr); > - if (fd > 0) { > - msg.memory.regions[fd_num].userspace_addr =3D reg->use= rspace_addr; > - msg.memory.regions[fd_num].memory_size =3D reg->memor= y_size; > - msg.memory.regions[fd_num].guest_phys_addr =3D reg->gu= est_phys_addr; > - msg.memory.regions[fd_num].mmap_offset =3D reg->usersp= ace_addr - > - (uintptr_t) qemu_get_ram_block_host_ptr(ram_addr); > - assert(fd_num < VHOST_MEMORY_MAX_NREGIONS); > - fds[fd_num++] =3D fd; > - } > - } > + if (!fd_num) { > + error_report("Failed initializing vhost-user memory map, " > + "consider using -object memory-backend-file share= =3Don"); > + return -1; > + } > =20 > - msg.memory.nregions =3D fd_num; > + msg.size =3D sizeof(m.memory.nregions); > + msg.size +=3D sizeof(m.memory.padding); > + msg.size +=3D fd_num * sizeof(VhostUserMemoryRegion); > =20 > - if (!fd_num) { > - error_report("Failed initializing vhost-user memory map, " > - "consider using -object memory-backend-file share=3D= on"); > - return -1; > - } > + vhost_user_write(dev, &msg, fds, fd_num); > =20 > - msg.size =3D sizeof(m.memory.nregions); > - msg.size +=3D sizeof(m.memory.padding); > - msg.size +=3D fd_num * sizeof(VhostUserMemoryRegion); > - > - break; > - > - case VHOST_USER_SET_LOG_FD: > - fds[fd_num++] =3D *((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 =3D sizeof(m.state); > - break; > - > - case VHOST_USER_GET_VRING_BASE: > - memcpy(&msg.state, arg, sizeof(struct vhost_vring_state)); > - msg.size =3D sizeof(m.state); > - need_reply =3D 1; > - break; > - > - case VHOST_USER_SET_VRING_ADDR: > - memcpy(&msg.addr, arg, sizeof(struct vhost_vring_addr)); > - msg.size =3D sizeof(m.addr); > - break; > - > - case VHOST_USER_SET_VRING_KICK: > - case VHOST_USER_SET_VRING_CALL: > - case VHOST_USER_SET_VRING_ERR: > - file =3D arg; > - msg.u64 =3D file->index & VHOST_USER_VRING_IDX_MASK; > - msg.size =3D sizeof(m.u64); > - if (ioeventfd_enabled() && file->fd > 0) { > - fds[fd_num++] =3D file->fd; > - } else { > - msg.u64 |=3D 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 =3D { > + .request =3D VHOST_USER_SET_VRING_ADDR, > + .flags =3D VHOST_USER_VERSION, > + .addr =3D *addr, > + .size =3D 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 =3D { > + .request =3D VHOST_USER_SET_VRING_NUM, > + .flags =3D VHOST_USER_VERSION, > + .state =3D *ring, > + .size =3D 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 =3D { > + .request =3D VHOST_USER_SET_VRING_BASE, > + .flags =3D VHOST_USER_VERSION, > + .state =3D *ring, > + .size =3D 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 =3D { > + .request =3D VHOST_USER_GET_VRING_BASE, > + .flags =3D VHOST_USER_VERSION, > + .state =3D *ring, > + .size =3D sizeof(*ring), > + }; > + > + vhost_user_write(dev, &msg, NULL, 0); > + > + if (vhost_user_read(dev, &msg) < 0) { > + return 0; > + } > + > + if (msg.request !=3D VHOST_USER_GET_VRING_BASE) { > + error_report("Received unexpected msg type. Expected %d receiv= ed %d", > + VHOST_USER_GET_FEATURES, msg.request); > return -1; > - break; > } > =20 > - if (vhost_user_write(dev, &msg, fds, fd_num) < 0) { > - return 0; > + if (msg.size !=3D sizeof(m.state)) { > + error_report("Received bad msg size."); > + return -1; > } > =20 > - if (need_reply) { > - if (vhost_user_read(dev, &msg) < 0) { > - return 0; > - } > + *ring =3D msg.state; > =20 > - if (msg_request !=3D msg.request) { > - error_report("Received unexpected msg type." > - " Expected %d received %d", msg_request, msg.reque= st); > - return -1; > - } > + return 0; > +} > =20 > - switch (msg_request) { > - case VHOST_USER_GET_FEATURES: > - if (msg.size !=3D sizeof(m.u64)) { > - error_report("Received bad msg size."); > - return -1; > - } > - *((__u64 *) arg) =3D msg.u64; > - break; > - case VHOST_USER_GET_VRING_BASE: > - if (msg.size !=3D 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 =3D 0; > + VhostUserMsg msg =3D { > + .request =3D request, > + .flags =3D VHOST_USER_VERSION, > + .u64 =3D file->index & VHOST_USER_VRING_IDX_MASK, > + .size =3D sizeof(m.u64), > + }; > + > + if (ioeventfd_enabled() && file->fd > 0) { > + fds[fd_num++] =3D file->fd; > + } else { > + msg.u64 |=3D VHOST_USER_VRING_NOFD_MASK; > } > =20 > + 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 =3D { > + .request =3D VHOST_USER_SET_FEATURES, > + .flags =3D VHOST_USER_VERSION, > + .u64 =3D features, > + .size =3D 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 =3D { > + .request =3D VHOST_USER_GET_FEATURES, > + .flags =3D VHOST_USER_VERSION, > + }; > + > + vhost_user_write(dev, &msg, NULL, 0); > + > + if (vhost_user_read(dev, &msg) < 0) { > + return 0; > + } > + > + if (msg.request !=3D VHOST_USER_GET_FEATURES) { > + error_report("Received unexpected msg type. Expected %d receiv= ed %d", > + VHOST_USER_GET_FEATURES, msg.request); > + return -1; > + } > + > + if (msg.size !=3D sizeof(m.u64)) { > + error_report("Received bad msg size."); > + return -1; > + } > + > + *features =3D msg.u64; > + > + return 0; > +} > + > +static int vhost_set_owner(struct vhost_dev *dev) > +{ > + VhostUserMsg msg =3D { > + .request =3D VHOST_USER_SET_OWNER, > + .flags =3D VHOST_USER_VERSION, > + }; > + > + vhost_user_write(dev, &msg, NULL, 0); > + > + return 0; > +} > + > +static int vhost_reset_owner(struct vhost_dev *dev) > +{ > + VhostUserMsg msg =3D { > + .request =3D VHOST_USER_RESET_OWNER, > + .flags =3D VHOST_USER_VERSION, > + }; > + > + vhost_user_write(dev, &msg, NULL, 0); > + > return 0; > } > =20 > @@ -402,7 +535,24 @@ static int vhost_user_cleanup(struct vhost_dev *de= v) > =20 > const VhostOps user_ops =3D { > .backend_type =3D VHOST_BACKEND_TYPE_USER, > - .vhost_call =3D vhost_user_call, > .vhost_backend_init =3D vhost_user_init, > - .vhost_backend_cleanup =3D vhost_user_cleanup > - }; > + .vhost_backend_cleanup =3D vhost_user_cleanup, > + > + .vhost_net_set_backend =3D vhost_net_set_backend, > + .vhost_scsi_set_endpoint =3D vhost_scsi_set_endpoint, > + .vhost_scsi_clear_endpoint =3D vhost_scsi_clear_endpoint, > + .vhost_scsi_get_abi_version =3D vhost_scsi_get_abi_version, > + .vhost_set_log_base =3D vhost_set_log_base, > + .vhost_set_mem_table =3D vhost_set_mem_table, > + .vhost_set_vring_addr =3D vhost_set_vring_addr, > + .vhost_set_vring_endian =3D vhost_set_vring_endian, > + .vhost_set_vring_num =3D vhost_set_vring_num, > + .vhost_set_vring_base =3D vhost_set_vring_base, > + .vhost_get_vring_base =3D vhost_get_vring_base, > + .vhost_set_vring_kick =3D vhost_set_vring_kick, > + .vhost_set_vring_call =3D vhost_set_vring_call, > + .vhost_set_features =3D vhost_set_features, > + .vhost_get_features =3D vhost_user_get_features, > + .vhost_set_owner =3D vhost_set_owner, > + .vhost_reset_owner =3D 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 vhos= t_dev* dev, uint64_t size) > =20 > /* inform backend of log switching, this must be done before > releasing the current log, to ensure no logging is lost */ > - r =3D dev->vhost_ops->vhost_call(dev, VHOST_SET_LOG_BASE, &log_bas= e); > + r =3D dev->vhost_ops->vhost_set_log_base(dev, log_base); > assert(r >=3D 0); > vhost_log_put(dev, true); > dev->log =3D log; > @@ -525,7 +525,7 @@ static void vhost_commit(MemoryListener *listener) > } > =20 > if (!dev->log_enabled) { > - r =3D dev->vhost_ops->vhost_call(dev, VHOST_SET_MEM_TABLE, dev= ->mem); > + r =3D dev->vhost_ops->vhost_set_mem_table(dev, dev->mem); > assert(r >=3D 0); > dev->memory_changed =3D 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 =3D dev->vhost_ops->vhost_call(dev, VHOST_SET_MEM_TABLE, dev->me= m); > + r =3D dev->vhost_ops->vhost_set_mem_table(dev, dev->mem); > assert(r >=3D 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_de= v *dev, > .log_guest_addr =3D vq->used_phys, > .flags =3D enable_log ? (1 << VHOST_VRING_F_LOG) : 0, > }; > - int r =3D dev->vhost_ops->vhost_call(dev, VHOST_SET_VRING_ADDR, &a= ddr); > + int r =3D 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 |=3D 0x1ULL << VHOST_F_LOG_ALL; > } > - r =3D dev->vhost_ops->vhost_call(dev, VHOST_SET_FEATURES, &feature= s); > + r =3D dev->vhost_ops->vhost_set_features(dev, features); > return r < 0 ? -errno : 0; > } > =20 > @@ -725,7 +725,7 @@ static int vhost_virtqueue_set_vring_endian_legacy(= struct vhost_dev *dev, > .num =3D is_big_endian > }; > =20 > - if (!dev->vhost_ops->vhost_call(dev, VHOST_SET_VRING_ENDIAN, &s)) = { > + if (!dev->vhost_ops->vhost_set_vring_endian(dev, &s)) { > return 0; > } > =20 > @@ -756,13 +756,13 @@ static int vhost_virtqueue_start(struct vhost_dev= *dev, > assert(idx >=3D dev->vq_index && idx < dev->vq_index + dev->nvqs); > =20 > vq->num =3D state.num =3D virtio_queue_get_num(vdev, idx); > - r =3D dev->vhost_ops->vhost_call(dev, VHOST_SET_VRING_NUM, &state)= ; > + r =3D dev->vhost_ops->vhost_set_vring_num(dev, &state); > if (r) { > return -errno; > } > =20 > state.num =3D virtio_queue_get_last_avail_idx(vdev, idx); > - r =3D dev->vhost_ops->vhost_call(dev, VHOST_SET_VRING_BASE, &state= ); > + r =3D 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, > } > =20 > file.fd =3D event_notifier_get_fd(virtio_queue_get_host_notifier(v= vq)); > - r =3D dev->vhost_ops->vhost_call(dev, VHOST_SET_VRING_KICK, &file)= ; > + r =3D dev->vhost_ops->vhost_set_vring_kick(dev, &file); > if (r) { > r =3D -errno; > goto fail_kick; > @@ -853,7 +853,7 @@ static void vhost_virtqueue_stop(struct vhost_dev *= dev, > }; > int r; > assert(idx >=3D dev->vq_index && idx < dev->vq_index + dev->nvqs); > - r =3D dev->vhost_ops->vhost_call(dev, VHOST_GET_VRING_BASE, &state= ); > + r =3D 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 *d= ev, > } > =20 > file.fd =3D event_notifier_get_fd(&vq->masked_notifier); > - r =3D dev->vhost_ops->vhost_call(dev, VHOST_SET_VRING_CALL, &file)= ; > + r =3D dev->vhost_ops->vhost_set_vring_call(dev, &file); > if (r) { > r =3D -errno; > goto fail_call; > @@ -941,12 +941,12 @@ int vhost_dev_init(struct vhost_dev *hdev, void *= opaque, > return -errno; > } > =20 > - r =3D hdev->vhost_ops->vhost_call(hdev, VHOST_SET_OWNER, NULL); > + r =3D hdev->vhost_ops->vhost_set_owner(hdev); > if (r < 0) { > goto fail; > } > =20 > - r =3D hdev->vhost_ops->vhost_call(hdev, VHOST_GET_FEATURES, &featu= res); > + r =3D 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 =3D event_notifier_get_fd(virtio_queue_get_guest_notif= ier(vvq)); > } > - r =3D hdev->vhost_ops->vhost_call(hdev, VHOST_SET_VRING_CALL, &fil= e); > + r =3D hdev->vhost_ops->vhost_set_vring_call(hdev, &file); > assert(r >=3D 0); > } > =20 > @@ -1144,7 +1144,7 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtI= ODevice *vdev) > if (r < 0) { > goto fail_features; > } > - r =3D hdev->vhost_ops->vhost_call(hdev, VHOST_SET_MEM_TABLE, hdev-= >mem); > + r =3D hdev->vhost_ops->vhost_set_mem_table(hdev, hdev->mem); > if (r < 0) { > r =3D -errno; > goto fail_mem; > @@ -1166,8 +1166,8 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtI= ODevice *vdev) > hdev->log_size =3D vhost_get_log_size(hdev); > hdev->log =3D vhost_log_get(hdev->log_size, share); > log_base =3D (uintptr_t)hdev->log->log; > - r =3D hdev->vhost_ops->vhost_call(hdev, VHOST_SET_LOG_BASE, > - hdev->log_size ? &log_base : N= ULL); > + r =3D hdev->vhost_ops->vhost_set_log_base(hdev, > + hdev->log_size ? log_b= ase : 0); > if (r < 0) { > r =3D -errno; > goto fail_log; > diff --git a/include/hw/virtio/vhost-backend.h b/include/hw/virtio/vhos= t-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; > =20 > struct vhost_dev; > +struct vhost_memory; > +struct vhost_vring_file; > +struct vhost_vring_state; > +struct vhost_vring_addr; > +struct vhost_scsi_target; > =20 > -typedef int (*vhost_call)(struct vhost_dev *dev, unsigned long int req= uest, > - void *arg); > typedef int (*vhost_backend_init)(struct vhost_dev *dev, void *opaque)= ; > typedef int (*vhost_backend_cleanup)(struct vhost_dev *dev); > =20 > +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 *ta= rget); > +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 b= ase); > +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 *rin= g); > +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; > =20 > extern const VhostOps user_ops; > --=20 > 2.4.3