From: "Michael S. Tsirkin" <mst@redhat.com>
To: Albert Esteve <aesteve@redhat.com>
Cc: qemu-devel@nongnu.org, kraxel@redhat.com,
marcandre.lureau@gmail.com, cohuck@redhat.com,
Fam Zheng <fam@euphon.net>
Subject: Re: [PATCH v3 3/4] vhost-user: add shared_object msg
Date: Thu, 22 Jun 2023 15:57:13 -0400 [thread overview]
Message-ID: <20230622155655-mutt-send-email-mst@kernel.org> (raw)
In-Reply-To: <20230524091333.201767-5-aesteve@redhat.com> <20230524091333.201767-4-aesteve@redhat.com>
On Wed, May 24, 2023 at 11:13:32AM +0200, Albert Esteve wrote:
> Add new vhost-user protocol message
> `VHOST_USER_BACKEND_SHARED_OBJECT`. This new
> message is sent from vhost-user back-ends
> to interact with the virtio-dmabuf table
> in order to add, remove, or lookup for
> virtio dma-buf shared objects.
>
> The action taken in the front-end depends
> on the type stored in the payload struct.
>
> In the libvhost-user library add helper
> functions to allow sending messages to
> interact with the virtio shared objects
> hash table.
>
> Signed-off-by: Albert Esteve <aesteve@redhat.com>
> ---
> docs/interop/vhost-user.rst | 15 ++++
> hw/virtio/vhost-user.c | 68 ++++++++++++++++++
> subprojects/libvhost-user/libvhost-user.c | 88 +++++++++++++++++++++++
> subprojects/libvhost-user/libvhost-user.h | 56 +++++++++++++++
> 4 files changed, 227 insertions(+)
>
> diff --git a/docs/interop/vhost-user.rst b/docs/interop/vhost-user.rst
> index 5a070adbc1..d3d8db41e5 100644
> --- a/docs/interop/vhost-user.rst
> +++ b/docs/interop/vhost-user.rst
> @@ -1528,6 +1528,21 @@ is sent by the front-end.
>
> The state.num field is currently reserved and must be set to 0.
>
> +``VHOST_USER_BACKEND_SHARED_OBJECT``
> + :id: 6
> + :equivalent ioctl: N/A
> + :request payload: ``struct VhostUserShared``
> + :reply payload: ``struct VhostUserShared`` (only for ``LOOKUP`` requests)
> +
> + Backends that need to interact with the virtio-dmabuf shared table API
> + can send this message. The operation is determined by the ``type`` member
> + of the payload struct. The valid values for the operation type are
> + ``VHOST_SHARED_OBJECT_*`` members, i.e., ``ADD``, ``LOOKUP``, and ``REMOVE``.
> + ``LOOKUP`` operations require the ``VHOST_USER_NEED_REPLY_MASK`` flag to be
> + set by the back-end, and the front-end will then send the dma-buf fd as
> + a response if the UUID matches an object in the table, or a negative value
> + otherwise.
> +
> .. _reply_ack:
>
> VHOST_USER_PROTOCOL_F_REPLY_ACK
> diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
> index 74a2a28663..5ac5f0eafd 100644
> --- a/hw/virtio/vhost-user.c
> +++ b/hw/virtio/vhost-user.c
> @@ -10,6 +10,7 @@
>
> #include "qemu/osdep.h"
> #include "qapi/error.h"
> +#include "hw/virtio/virtio-dmabuf.h"
> #include "hw/virtio/vhost.h"
> #include "hw/virtio/vhost-user.h"
> #include "hw/virtio/vhost-backend.h"
> @@ -20,6 +21,7 @@
> #include "sysemu/kvm.h"
> #include "qemu/error-report.h"
> #include "qemu/main-loop.h"
> +#include "qemu/uuid.h"
> #include "qemu/sockets.h"
> #include "sysemu/runstate.h"
> #include "sysemu/cryptodev.h"
> @@ -128,6 +130,7 @@ typedef enum VhostUserSlaveRequest {
> VHOST_USER_BACKEND_IOTLB_MSG = 1,
> VHOST_USER_BACKEND_CONFIG_CHANGE_MSG = 2,
> VHOST_USER_BACKEND_VRING_HOST_NOTIFIER_MSG = 3,
> + VHOST_USER_BACKEND_SHARED_OBJECT = 6,
> VHOST_USER_BACKEND_MAX
> } VhostUserSlaveRequest;
>
> @@ -190,6 +193,18 @@ typedef struct VhostUserInflight {
> uint16_t queue_size;
> } VhostUserInflight;
>
> +typedef enum VhostUserSharedType {
> + VHOST_SHARED_OBJECT_ADD = 0,
> + VHOST_SHARED_OBJECT_LOOKUP,
> + VHOST_SHARED_OBJECT_REMOVE,
> +} VhostUserSharedType;
> +
> +typedef struct VhostUserShared {
> + unsigned char uuid[16];
> + VhostUserSharedType type;
> + int dmabuf_fd;
> +} VhostUserShared;
> +
> typedef struct {
> VhostUserRequest request;
>
> @@ -214,6 +229,7 @@ typedef union {
> VhostUserCryptoSession session;
> VhostUserVringArea area;
> VhostUserInflight inflight;
> + VhostUserShared object;
> } VhostUserPayload;
>
> typedef struct VhostUserMsg {
> @@ -1582,6 +1598,52 @@ static int vhost_user_slave_handle_vring_host_notifier(struct vhost_dev *dev,
> return 0;
> }
>
> +static int vhost_user_backend_handle_shared_object(VhostUserShared *object)
> +{
> + QemuUUID uuid;
> + memcpy(uuid.data, object->uuid, sizeof(object->uuid));
> +
> + switch (object->type) {
> + case VHOST_SHARED_OBJECT_ADD:
> + return virtio_add_dmabuf(&uuid, object->dmabuf_fd);
> + case VHOST_SHARED_OBJECT_LOOKUP:
> + object->dmabuf_fd = virtio_lookup_dmabuf(&uuid);
> + if (object->dmabuf_fd < 0) {
> + return object->dmabuf_fd;
> + }
> + break;
> + case VHOST_SHARED_OBJECT_REMOVE:
> + return virtio_remove_resource(&uuid);
> + }
> +
> + return 0;
> +}
> +
> +static bool
> +vhost_user_backend_send_dmabuf_fd(QIOChannel *ioc, VhostUserHeader *hdr,
> + VhostUserPayload *payload)
> +{
> + Error *local_err = NULL;
> + struct iovec iov[2];
> + if (hdr->flags & VHOST_USER_NEED_REPLY_MASK) {
> + hdr->flags &= ~VHOST_USER_NEED_REPLY_MASK;
> + hdr->flags |= VHOST_USER_REPLY_MASK;
> +
> + hdr->size = sizeof(payload->object);
> +
> + iov[0].iov_base = hdr;
> + iov[0].iov_len = VHOST_USER_HDR_SIZE;
> + iov[1].iov_base = payload;
> + iov[1].iov_len = hdr->size;
> +
> + if (qio_channel_writev_all(ioc, iov, ARRAY_SIZE(iov), &local_err)) {
> + error_report_err(local_err);
> + return false;
> + }
> + }
> + return true;
> +}
> +
> static void close_slave_channel(struct vhost_user *u)
> {
> g_source_destroy(u->slave_src);
> @@ -1639,6 +1701,12 @@ static gboolean slave_read(QIOChannel *ioc, GIOCondition condition,
> ret = vhost_user_slave_handle_vring_host_notifier(dev, &payload.area,
> fd ? fd[0] : -1);
> break;
> + case VHOST_USER_BACKEND_SHARED_OBJECT:
> + ret = vhost_user_backend_handle_shared_object(&payload.object);
> + if (!vhost_user_backend_send_dmabuf_fd(ioc, &hdr, &payload)) {
> + goto err;
> + }
> + break;
> default:
> error_report("Received unexpected msg type: %d.", hdr.request);
> ret = -EINVAL;
> diff --git a/subprojects/libvhost-user/libvhost-user.c b/subprojects/libvhost-user/libvhost-user.c
> index 8fb61e2df2..27f16d292a 100644
> --- a/subprojects/libvhost-user/libvhost-user.c
> +++ b/subprojects/libvhost-user/libvhost-user.c
> @@ -1403,6 +1403,94 @@ bool vu_set_queue_host_notifier(VuDev *dev, VuVirtq *vq, int fd,
> return vu_process_message_reply(dev, &vmsg);
> }
>
> +bool
> +vu_get_shared_object(VuDev *dev, unsigned char uuid[UUID_LEN], int *dmabuf_fd)
> +{
> + bool result = false;
> + VhostUserMsg msg_reply;
> + VhostUserMsg msg = {
> + .request = VHOST_USER_BACKEND_SHARED_OBJECT,
> + .size = sizeof(msg.payload.object),
> + .flags = VHOST_USER_VERSION | VHOST_USER_NEED_REPLY_MASK,
> + .payload.object = {
> + .type = VHOST_SHARED_OBJECT_LOOKUP,
> + },
> + };
> +
> + memcpy(msg.payload.object.uuid, uuid, sizeof(uuid[0]) * UUID_LEN);
> +
> + pthread_mutex_lock(&dev->slave_mutex);
> + if (!vu_message_write(dev, dev->slave_fd, &msg)) {
> + goto out;
> + }
> +
> + if (!vu_message_read_default(dev, dev->slave_fd, &msg_reply)) {
> + goto out;
> + }
> +
> + if (msg_reply.request != msg.request) {
> + DPRINT("Received unexpected msg type. Expected %d, received %d",
> + msg.request, msg_reply.request);
> + goto out;
> + }
> +
> + *dmabuf_fd = msg_reply.payload.object.dmabuf_fd;
> + result = *dmabuf_fd > 0;
> +out:
> + pthread_mutex_unlock(&dev->slave_mutex);
> +
> + return result;
> +}
> +
> +static bool
> +vu_send_message(VuDev *dev, VhostUserMsg *vmsg)
> +{
> + bool result = false;
> + pthread_mutex_lock(&dev->slave_mutex);
> + if (!vu_message_write(dev, dev->slave_fd, vmsg)) {
> + goto out;
> + }
> +
> + result = true;
> +out:
> + pthread_mutex_unlock(&dev->slave_mutex);
> +
> + return result;
> +}
> +
> +bool
> +vu_add_shared_object(VuDev *dev, unsigned char uuid[UUID_LEN], int dmabuf_fd)
> +{
> + VhostUserMsg msg = {
> + .request = VHOST_USER_BACKEND_SHARED_OBJECT,
> + .size = sizeof(msg.payload.object),
> + .flags = VHOST_USER_VERSION,
> + .payload.object = {
> + .dmabuf_fd = dmabuf_fd,
> + .type = VHOST_SHARED_OBJECT_ADD,
> + },
> + };
> + memcpy(msg.payload.object.uuid, uuid, sizeof(uuid[0]) * UUID_LEN);
> +
> + return vu_send_message(dev, &msg);
> +}
> +
> +bool
> +vu_rm_shared_object(VuDev *dev, unsigned char uuid[UUID_LEN])
> +{
> + VhostUserMsg msg = {
> + .request = VHOST_USER_BACKEND_SHARED_OBJECT,
> + .size = sizeof(msg.payload.object),
> + .flags = VHOST_USER_VERSION,
> + .payload.object = {
> + .type = VHOST_SHARED_OBJECT_REMOVE,
> + },
> + };
> + memcpy(msg.payload.object.uuid, uuid, sizeof(uuid[0]) * UUID_LEN);
> +
> + return vu_send_message(dev, &msg);
> +}
> +
> static bool
> vu_set_vring_call_exec(VuDev *dev, VhostUserMsg *vmsg)
> {
> diff --git a/subprojects/libvhost-user/libvhost-user.h b/subprojects/libvhost-user/libvhost-user.h
> index 49208cceaa..a43d115bd7 100644
> --- a/subprojects/libvhost-user/libvhost-user.h
> +++ b/subprojects/libvhost-user/libvhost-user.h
> @@ -119,6 +119,7 @@ typedef enum VhostUserSlaveRequest {
> VHOST_USER_BACKEND_VRING_HOST_NOTIFIER_MSG = 3,
> VHOST_USER_BACKEND_VRING_CALL = 4,
> VHOST_USER_BACKEND_VRING_ERR = 5,
> + VHOST_USER_BACKEND_SHARED_OBJECT = 6,
> VHOST_USER_BACKEND_MAX
> } VhostUserSlaveRequest;
>
> @@ -172,6 +173,20 @@ typedef struct VhostUserInflight {
> uint16_t queue_size;
> } VhostUserInflight;
>
> +typedef enum VhostUserSharedType {
> + VHOST_SHARED_OBJECT_ADD = 0,
> + VHOST_SHARED_OBJECT_LOOKUP,
> + VHOST_SHARED_OBJECT_REMOVE,
> +} VhostUserSharedType;
> +
> +#define UUID_LEN 16
> +
> +typedef struct VhostUserShared {
> + unsigned char uuid[UUID_LEN];
> + VhostUserSharedType type;
> + int dmabuf_fd;
> +} VhostUserShared;
> +
> #if defined(_WIN32) && (defined(__x86_64__) || defined(__i386__))
> # define VU_PACKED __attribute__((gcc_struct, packed))
> #else
> @@ -199,6 +214,7 @@ typedef struct VhostUserMsg {
> VhostUserConfig config;
> VhostUserVringArea area;
> VhostUserInflight inflight;
> + VhostUserShared object;
> } payload;
>
> int fds[VHOST_MEMORY_BASELINE_NREGIONS];
> @@ -539,6 +555,46 @@ void vu_set_queue_handler(VuDev *dev, VuVirtq *vq,
> bool vu_set_queue_host_notifier(VuDev *dev, VuVirtq *vq, int fd,
> int size, int offset);
>
> +/**
> + * vu_get_shared_object:
> + * @dev: a VuDev context
> + * @uuid: UUID of the shared object
> + * @dmabuf_fd: output dma-buf file descriptor
> + *
> + * Lookup for a virtio shared object (i.e., dma-buf fd) associated with the
> + * received UUID. Result, if found, is stored in the dmabuf_fd argument.
> + *
> + * Returns: whether the virtio object was found.
> + */
> +bool vu_get_shared_object(VuDev *dev, unsigned char uuid[UUID_LEN],
> + int *dmabuf_fd);
> +
> +/**
> + * vu_add_shared_object:
> + * @dev: a VuDev context
> + * @uuid: UUID of the shared object
> + * @dmabuf_fd: output dma-buf file descriptor
> + *
> + * Stores a new shared object (i.e., dma-buf fd) in the hash table, and
trailing whitespace. I fixed it up.
> + * associates it with the received UUID.
> + *
> + * Returns: TRUE on success, FALSE on failure.
> + */
> +bool vu_add_shared_object(VuDev *dev, unsigned char uuid[UUID_LEN],
> + int dmabuf_fd);
> +
> +/**
> + * vu_rm_shared_object:
> + * @dev: a VuDev context
> + * @uuid: UUID of the shared object
> + *
> + * Removes a shared object (i.e., dma-buf fd) associated with the
> + * received UUID from the hash table.
> + *
> + * Returns: TRUE on success, FALSE on failure.
> + */
> +bool vu_rm_shared_object(VuDev *dev, unsigned char uuid[UUID_LEN]);
> +
> /**
> * vu_queue_set_notification:
> * @dev: a VuDev context
> --
> 2.40.0
On Wed, May 24, 2023 at 11:13:33AM +0200, Albert Esteve wrote:
> Refactor code to send response message so that
> all common parts both for the common REPLY_ACK
> case, and other data responses, can call it and
> avoid code repetition.
>
> Signed-off-by: Albert Esteve <aesteve@redhat.com>
> ---
> hw/virtio/vhost-user.c | 52 +++++++++++++++++++-----------------------
> 1 file changed, 24 insertions(+), 28 deletions(-)
>
> diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
> index 5ac5f0eafd..b888f2c177 100644
> --- a/hw/virtio/vhost-user.c
> +++ b/hw/virtio/vhost-user.c
> @@ -1619,28 +1619,36 @@ static int vhost_user_backend_handle_shared_object(VhostUserShared *object)
> return 0;
> }
>
> -static bool
> -vhost_user_backend_send_dmabuf_fd(QIOChannel *ioc, VhostUserHeader *hdr,
> - VhostUserPayload *payload)
> +static bool vhost_user_send_resp(QIOChannel *ioc, VhostUserHeader *hdr,
> + VhostUserPayload *payload)
> {
> Error *local_err = NULL;
> struct iovec iov[2];
> - if (hdr->flags & VHOST_USER_NEED_REPLY_MASK) {
> - hdr->flags &= ~VHOST_USER_NEED_REPLY_MASK;
> - hdr->flags |= VHOST_USER_REPLY_MASK;
> + hdr->flags &= ~VHOST_USER_NEED_REPLY_MASK;
> + hdr->flags |= VHOST_USER_REPLY_MASK;
>
> - hdr->size = sizeof(payload->object);
> + iov[0].iov_base = hdr;
> + iov[0].iov_len = VHOST_USER_HDR_SIZE;
> + iov[1].iov_base = payload;
> + iov[1].iov_len = hdr->size;
> +
> + if (qio_channel_writev_all(ioc, iov, ARRAY_SIZE(iov), &local_err)) {
> + error_report_err(local_err);
> + return false;
> + }
>
> - iov[0].iov_base = hdr;
> - iov[0].iov_len = VHOST_USER_HDR_SIZE;
> - iov[1].iov_base = payload;
> - iov[1].iov_len = hdr->size;
> + return true;
> +}
>
> - if (qio_channel_writev_all(ioc, iov, ARRAY_SIZE(iov), &local_err)) {
> - error_report_err(local_err);
> - return false;
> - }
> +static bool
> +vhost_user_backend_send_dmabuf_fd(QIOChannel *ioc, VhostUserHeader *hdr,
> + VhostUserPayload *payload)
> +{
> + if (hdr->flags & VHOST_USER_NEED_REPLY_MASK) {
> + hdr->size = sizeof(payload->object);
> + return vhost_user_send_resp(ioc, hdr, payload);
> }
> +
> return true;
> }
>
> @@ -1717,22 +1725,10 @@ static gboolean slave_read(QIOChannel *ioc, GIOCondition condition,
> * directly in their request handlers.
> */
> if (hdr.flags & VHOST_USER_NEED_REPLY_MASK) {
> - struct iovec iovec[2];
> -
> -
> - hdr.flags &= ~VHOST_USER_NEED_REPLY_MASK;
> - hdr.flags |= VHOST_USER_REPLY_MASK;
> -
> payload.u64 = !!ret;
> hdr.size = sizeof(payload.u64);
>
> - iovec[0].iov_base = &hdr;
> - iovec[0].iov_len = VHOST_USER_HDR_SIZE;
> - iovec[1].iov_base = &payload;
> - iovec[1].iov_len = hdr.size;
> -
> - if (qio_channel_writev_all(ioc, iovec, ARRAY_SIZE(iovec), &local_err)) {
> - error_report_err(local_err);
> + if (!vhost_user_send_resp(ioc, &hdr, &payload)) {
> goto err;
> }
> }
> --
> 2.40.0
next prev parent reply other threads:[~2023-06-22 19:57 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-05-24 9:13 [PATCH v3 0/4] Virtio shared dma-buf Albert Esteve
2023-05-24 9:13 ` [PATCH v3 1/4] uuid: add hash_func and equal_func Albert Esteve
2023-05-24 9:13 ` [PATCH v3 2/4] virtio-dmabuf: introduce virtio-dmabuf Albert Esteve
2023-05-24 9:13 ` [PATCH v3 3/4] vhost-user: add shared_object msg Albert Esteve
2023-06-22 19:57 ` Michael S. Tsirkin [this message]
2023-06-22 20:18 ` Marc-André Lureau
2023-06-23 7:45 ` Albert Esteve
2023-06-23 6:45 ` Michael S. Tsirkin
2023-06-23 7:19 ` Albert Esteve
2023-06-23 7:32 ` Michael S. Tsirkin
2023-06-23 13:46 ` Albert Esteve
2023-06-23 8:14 ` Michael S. Tsirkin
2023-06-23 12:08 ` Albert Esteve
2023-05-24 9:13 ` [PATCH v3 4/4] vhost-user: refactor send_resp code Albert Esteve
2023-06-23 6:48 ` Michael S. Tsirkin
2023-06-21 8:20 ` [PATCH v3 0/4] Virtio shared dma-buf Albert Esteve
2023-06-21 20:25 ` Michael S. Tsirkin
2023-06-22 19:53 ` Michael S. Tsirkin
2023-06-23 6:49 ` Michael S. Tsirkin
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=20230622155655-mutt-send-email-mst@kernel.org \
--to=mst@redhat.com \
--cc=aesteve@redhat.com \
--cc=cohuck@redhat.com \
--cc=fam@euphon.net \
--cc=kraxel@redhat.com \
--cc=marcandre.lureau@gmail.com \
--cc=qemu-devel@nongnu.org \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.