qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: "Marc-André Lureau" <mlureau@redhat.com>
To: "Michael S. Tsirkin" <mst@redhat.com>
Cc: haifeng lin <haifeng.lin@huawei.com>,
	thibaut collet <thibaut.collet@6wind.com>,
	jasowang@redhat.com, qemu-devel@nongnu.org, pbonzini@redhat.com,
	marcandre lureau <marcandre.lureau@redhat.com>
Subject: Re: [Qemu-devel] [PATCH v4 09/22] vhost: use a function for each call
Date: Mon, 21 Sep 2015 10:05:56 -0400 (EDT)	[thread overview]
Message-ID: <466418414.14560298.1442844356149.JavaMail.zimbra@redhat.com> (raw)
In-Reply-To: <20150921115644-mutt-send-email-mst@redhat.com>



----- Original Message -----
> On Sat, Sep 19, 2015 at 12:12:00PM +0200, marcandre.lureau@redhat.com wrote:
> > From: Marc-André Lureau <marcandre.lureau@redhat.com>
> > 
> > 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 <marcandre.lureau@redhat.com>
> 
> OK but I would rather not make logging feature depend on the
> refactoring.

The refactoring is straightforward, but I can split this patch.

> 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.
> 

ok

> > ---
> >  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;
> >  }
> >  
> > @@ -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
> 

  reply	other threads:[~2015-09-21 14:06 UTC|newest]

Thread overview: 41+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-09-19 10:11 [Qemu-devel] [PATCH v4 00/22] vhost-user: add migration support marcandre.lureau
2015-09-19 10:11 ` [Qemu-devel] [PATCH v4 01/22] vhost-user: refactor ioctl translation marcandre.lureau
2015-09-19 10:11 ` [Qemu-devel] [PATCH v4 02/22] vhost-user: add protocol feature negotiation marcandre.lureau
2015-09-19 10:11 ` [Qemu-devel] [PATCH v4 03/22] vhost-user: unit test for new messages marcandre.lureau
2015-09-19 10:11 ` [Qemu-devel] [PATCH v4 04/22] configure: probe for memfd marcandre.lureau
2015-09-19 10:11 ` [Qemu-devel] [PATCH v4 05/22] util: add linux-only memfd fallback marcandre.lureau
2015-09-19 10:11 ` [Qemu-devel] [PATCH v4 06/22] util: add memfd helpers marcandre.lureau
2015-09-19 10:11 ` [Qemu-devel] [PATCH v4 07/22] vhost: alloc shareable log marcandre.lureau
2015-09-21  8:44   ` Michael S. Tsirkin
2015-09-21 14:02     ` Marc-André Lureau
2015-09-21 19:29       ` Michael S. Tsirkin
2015-09-21 21:44         ` Marc-André Lureau
2015-09-22 10:12           ` Michael S. Tsirkin
2015-09-22 11:01             ` Marc-André Lureau
2015-09-22 11:41               ` Michael S. Tsirkin
2015-09-22 11:50                 ` Marc-André Lureau
2015-09-22 11:54                   ` Michael S. Tsirkin
2015-09-19 10:11 ` [Qemu-devel] [PATCH v4 08/22] vhost: document log resizing marcandre.lureau
2015-09-19 10:12 ` [Qemu-devel] [PATCH v4 09/22] vhost: use a function for each call marcandre.lureau
2015-09-21  7:33   ` Thibaut Collet
2015-09-21  8:56     ` Michael S. Tsirkin
2015-09-21  8:58   ` Michael S. Tsirkin
2015-09-21 14:05     ` Marc-André Lureau [this message]
2015-09-19 10:12 ` [Qemu-devel] [PATCH v4 10/22] vhost-user: remove vhost_user_request_translate() marcandre.lureau
2015-09-19 10:12 ` [Qemu-devel] [PATCH v4 11/22] vhost-user: send log shm fd along with log_base marcandre.lureau
2015-09-21  8:49   ` Michael S. Tsirkin
2015-09-21 14:05     ` Marc-André Lureau
2015-09-21 19:30       ` Michael S. Tsirkin
2015-09-19 10:12 ` [Qemu-devel] [PATCH v4 12/22] vhost: only use shared log if in use by backend marcandre.lureau
2015-09-21  8:46   ` Michael S. Tsirkin
2015-09-21 14:03     ` Marc-André Lureau
2015-09-19 10:12 ` [Qemu-devel] [PATCH v4 13/22] vhost-user: document migration log marcandre.lureau
2015-09-19 10:12 ` [Qemu-devel] [PATCH v4 14/22] net: add trace_vhost_user_event marcandre.lureau
2015-09-19 10:12 ` [Qemu-devel] [PATCH v4 15/22] vhost user: add support of live migration marcandre.lureau
2015-09-19 10:12 ` [Qemu-devel] [PATCH v4 16/22] vhost user: add rarp sending after live migration for legacy guest marcandre.lureau
2015-09-19 10:12 ` [Qemu-devel] [PATCH v4 17/22] vhost-user-test: move wait_for_fds() out marcandre.lureau
2015-09-19 10:12 ` [Qemu-devel] [PATCH v4 18/22] vhost-user-test: remove useless static check marcandre.lureau
2015-09-19 10:12 ` [Qemu-devel] [PATCH v4 19/22] vhost-user-test: wrap server in TestServer struct marcandre.lureau
2015-09-19 10:12 ` [Qemu-devel] [PATCH v4 20/22] vhost-user-test: learn to tweak various qemu arguments marcandre.lureau
2015-09-19 10:12 ` [Qemu-devel] [PATCH v4 21/22] vhost-user-test: add live-migration test marcandre.lureau
2015-09-19 10:12 ` [Qemu-devel] [PATCH v4 22/22] vhost-user-test: check ownership during migration marcandre.lureau

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=466418414.14560298.1442844356149.JavaMail.zimbra@redhat.com \
    --to=mlureau@redhat.com \
    --cc=haifeng.lin@huawei.com \
    --cc=jasowang@redhat.com \
    --cc=marcandre.lureau@redhat.com \
    --cc=mst@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=thibaut.collet@6wind.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).