Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backport fix #69

Open
wants to merge 14 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions doc/guides/prog_guide/vhost_lib.rst
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,12 @@ The following is an overview of some key Vhost API functions:
Clear inflight packets which are submitted to DMA engine in vhost async data
path. Completed packets are returned to applications through ``pkts``.

* ``rte_vhost_vring_call_nonblock(int vid, uint16_t vring_idx)``

Notify the guest that used descriptors have been added to the vring. This function
will return -EAGAIN when vq's access lock is held by other thread, user should try
again later.

Vhost-user Implementations
--------------------------

Expand Down
15 changes: 15 additions & 0 deletions lib/vhost/rte_vhost.h
Original file line number Diff line number Diff line change
Expand Up @@ -935,6 +935,21 @@ rte_vhost_clr_inflight_desc_packed(int vid, uint16_t vring_idx,
*/
int rte_vhost_vring_call(int vid, uint16_t vring_idx);

/**
* Notify the guest that used descriptors have been added to the vring. This
* function acts as a memory barrier. This function will return -EAGAIN when
* vq's access lock is held by other thread, user should try again later.
*
* @param vid
* vhost device ID
* @param vring_idx
* vring index
* @return
* 0 on success, -1 on failure, -EAGAIN for another retry
*/
__rte_experimental
int rte_vhost_vring_call_nonblock(int vid, uint16_t vring_idx);

/**
* Get vhost RX queue avail count.
*
Expand Down
16 changes: 9 additions & 7 deletions lib/vhost/socket.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,10 +128,12 @@ read_fd_message(char *ifname, int sockfd, char *buf, int buflen, int *fds, int m
return ret;
}

if (msgh.msg_flags & (MSG_TRUNC | MSG_CTRUNC)) {
if (msgh.msg_flags & MSG_TRUNC)
VHOST_LOG_CONFIG(ERR, "(%s) truncated msg (fd %d)\n", ifname, sockfd);
return -1;
}

/* MSG_CTRUNC may be caused by LSM misconfiguration */
if (msgh.msg_flags & MSG_CTRUNC)
VHOST_LOG_CONFIG(ERR, "(%s) truncated control data (fd %d)\n", ifname, sockfd);

for (cmsg = CMSG_FIRSTHDR(&msgh); cmsg != NULL;
cmsg = CMSG_NXTHDR(&msgh, cmsg)) {
Expand Down Expand Up @@ -514,17 +516,17 @@ vhost_user_reconnect_init(void)

ret = pthread_mutex_init(&reconn_list.mutex, NULL);
if (ret < 0) {
VHOST_LOG_CONFIG(ERR, "%s: failed to initialize mutex", __func__);
VHOST_LOG_CONFIG(ERR, "%s: failed to initialize mutex\n", __func__);
return ret;
}
TAILQ_INIT(&reconn_list.head);

ret = rte_ctrl_thread_create(&reconn_tid, "vhost_reconn", NULL,
vhost_user_client_reconnect, NULL);
if (ret != 0) {
VHOST_LOG_CONFIG(ERR, "failed to create reconnect thread");
VHOST_LOG_CONFIG(ERR, "failed to create reconnect thread\n");
if (pthread_mutex_destroy(&reconn_list.mutex))
VHOST_LOG_CONFIG(ERR, "%s: failed to destroy reconnect mutex", __func__);
VHOST_LOG_CONFIG(ERR, "%s: failed to destroy reconnect mutex\n", __func__);
}

return ret;
Expand Down Expand Up @@ -1147,7 +1149,7 @@ rte_vhost_driver_start(const char *path)
"vhost-events", NULL, fdset_event_dispatch,
&vhost_user.fdset);
if (ret != 0) {
VHOST_LOG_CONFIG(ERR, "(%s) failed to create fdset handling thread", path);
VHOST_LOG_CONFIG(ERR, "(%s) failed to create fdset handling thread\n", path);

fdset_pipe_uninit(&vhost_user.fdset);
return -1;
Expand Down
10 changes: 9 additions & 1 deletion lib/vhost/vdpa.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "rte_vdpa.h"
#include "vdpa_driver.h"
#include "vhost.h"
#include "iotlb.h"

/** Double linked list of vDPA devices. */
TAILQ_HEAD(vdpa_device_list, rte_vdpa_device);
Expand Down Expand Up @@ -175,17 +176,21 @@ rte_vdpa_relay_vring_used(int vid, uint16_t qid, void *vring_m)
if (unlikely(nr_descs > vq->size))
return -1;

vhost_user_iotlb_rd_lock(vq);
desc_ring = (struct vring_desc *)(uintptr_t)
vhost_iova_to_vva(dev, vq,
vq->desc[desc_id].addr, &dlen,
VHOST_ACCESS_RO);
vhost_user_iotlb_rd_unlock(vq);
if (unlikely(!desc_ring))
return -1;

if (unlikely(dlen < vq->desc[desc_id].len)) {
vhost_user_iotlb_rd_lock(vq);
idesc = vhost_alloc_copy_ind_table(dev, vq,
vq->desc[desc_id].addr,
vq->desc[desc_id].len);
vhost_user_iotlb_rd_unlock(vq);
if (unlikely(!idesc))
return -1;

Expand All @@ -202,9 +207,12 @@ rte_vdpa_relay_vring_used(int vid, uint16_t qid, void *vring_m)
if (unlikely(nr_descs-- == 0))
goto fail;
desc = desc_ring[desc_id];
if (desc.flags & VRING_DESC_F_WRITE)
if (desc.flags & VRING_DESC_F_WRITE) {
vhost_user_iotlb_rd_lock(vq);
vhost_log_write_iova(dev, vq, desc.addr,
desc.len);
vhost_user_iotlb_rd_unlock(vq);
}
desc_id = desc.next;
} while (desc.flags & VRING_DESC_F_NEXT);

Expand Down
1 change: 1 addition & 0 deletions lib/vhost/version.map
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ EXPERIMENTAL {

# added in 22.03
rte_vhost_async_dma_configure;
rte_vhost_vring_call_nonblock;
};

INTERNAL {
Expand Down
30 changes: 30 additions & 0 deletions lib/vhost/vhost.c
Original file line number Diff line number Diff line change
Expand Up @@ -1325,6 +1325,36 @@ rte_vhost_vring_call(int vid, uint16_t vring_idx)
return ret;
}

int
rte_vhost_vring_call_nonblock(int vid, uint16_t vring_idx)
{
struct virtio_net *dev;
struct vhost_virtqueue *vq;

dev = get_device(vid);
if (!dev)
return -1;

if (vring_idx >= VHOST_MAX_VRING)
return -1;

vq = dev->virtqueue[vring_idx];
if (!vq)
return -1;

if (!rte_spinlock_trylock(&vq->access_lock))
return -EAGAIN;

if (vq_is_packed(dev))
vhost_vring_call_packed(dev, vq);
else
vhost_vring_call_split(dev, vq);

rte_spinlock_unlock(&vq->access_lock);

return 0;
}

uint16_t
rte_vhost_avail_entries(int vid, uint16_t queue_id)
{
Expand Down
13 changes: 8 additions & 5 deletions lib/vhost/vhost.h
Original file line number Diff line number Diff line change
Expand Up @@ -766,7 +766,10 @@ hva_to_gpa(struct virtio_net *dev, uint64_t vva, uint64_t len)
static __rte_always_inline struct virtio_net *
get_device(int vid)
{
struct virtio_net *dev = vhost_devices[vid];
struct virtio_net *dev = NULL;

if (likely(vid >= 0 && vid < RTE_MAX_VHOST_DEVICE))
dev = vhost_devices[vid];

if (unlikely(!dev)) {
VHOST_LOG_CONFIG(ERR,
Expand Down Expand Up @@ -863,9 +866,9 @@ vhost_vring_call_split(struct virtio_net *dev, struct vhost_virtqueue *vq)
vhost_used_event(vq),
old, new);

if ((vhost_need_event(vhost_used_event(vq), new, old) &&
(vq->callfd >= 0)) ||
unlikely(!signalled_used_valid)) {
if ((vhost_need_event(vhost_used_event(vq), new, old) ||
unlikely(!signalled_used_valid)) &&
vq->callfd >= 0) {
eventfd_write(vq->callfd, (eventfd_t) 1);
if (dev->notify_ops->guest_notified)
dev->notify_ops->guest_notified(dev->vid);
Expand Down Expand Up @@ -928,7 +931,7 @@ vhost_vring_call_packed(struct virtio_net *dev, struct vhost_virtqueue *vq)
if (vhost_need_event(off, new, old))
kick = true;
kick:
if (kick) {
if (kick && vq->callfd >= 0) {
eventfd_write(vq->callfd, (eventfd_t)1);
if (dev->notify_ops->guest_notified)
dev->notify_ops->guest_notified(dev->vid);
Expand Down
49 changes: 32 additions & 17 deletions lib/vhost/vhost_user.c
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,8 @@ async_dma_map(struct virtio_net *dev, bool do_map)
return;

/* DMA mapping errors won't stop VHOST_USER_SET_MEM_TABLE. */
VHOST_LOG_CONFIG(ERR, "DMA engine map failed\n");
VHOST_LOG_CONFIG(ERR, "(%s) DMA engine map failed\n",
dev->ifname);
}
}

Expand All @@ -190,7 +191,8 @@ async_dma_map(struct virtio_net *dev, bool do_map)
if (rte_errno == EINVAL)
return;

VHOST_LOG_CONFIG(ERR, "DMA engine unmap failed\n");
VHOST_LOG_CONFIG(ERR, "(%s) DMA engine unmap failed\n",
dev->ifname);
}
}
}
Expand Down Expand Up @@ -852,7 +854,8 @@ add_one_guest_page(struct virtio_net *dev, uint64_t guest_phys_addr,
dev->max_guest_pages * sizeof(*page),
RTE_CACHE_LINE_SIZE);
if (dev->guest_pages == NULL) {
VHOST_LOG_CONFIG(ERR, "cannot realloc guest_pages\n");
VHOST_LOG_CONFIG(ERR, "(%s) cannot realloc guest_pages\n",
dev->ifname);
rte_free(old_pages);
return -1;
}
Expand Down Expand Up @@ -1701,7 +1704,7 @@ static int vhost_user_set_vring_err(struct virtio_net **pdev,

if (!(ctx->msg.payload.u64 & VHOST_USER_VRING_NOFD_MASK))
close(ctx->fds[0]);
VHOST_LOG_CONFIG(INFO, "(%s) not implemented\n", dev->ifname);
VHOST_LOG_CONFIG(DEBUG, "(%s) not implemented\n", dev->ifname);

return RTE_VHOST_MSG_RESULT_OK;
}
Expand Down Expand Up @@ -2053,7 +2056,9 @@ vhost_user_get_vring_base(struct virtio_net **pdev,

vhost_user_iotlb_flush_all(vq);

rte_spinlock_lock(&vq->access_lock);
vring_invalidate(dev, vq);
rte_spinlock_unlock(&vq->access_lock);

return RTE_VHOST_MSG_RESULT_REPLY;
}
Expand Down Expand Up @@ -2241,7 +2246,7 @@ static int vhost_user_set_log_fd(struct virtio_net **pdev,
return RTE_VHOST_MSG_RESULT_ERR;

close(ctx->fds[0]);
VHOST_LOG_CONFIG(INFO, "(%s) not implemented.\n", dev->ifname);
VHOST_LOG_CONFIG(DEBUG, "(%s) not implemented.\n", dev->ifname);

return RTE_VHOST_MSG_RESULT_OK;
}
Expand Down Expand Up @@ -2440,6 +2445,7 @@ vhost_user_iotlb_msg(struct virtio_net **pdev,
if (is_vring_iotlb(dev, vq, imsg)) {
rte_spinlock_lock(&vq->access_lock);
*pdev = dev = translate_ring_addresses(dev, i);
vq = dev->virtqueue[i];
rte_spinlock_unlock(&vq->access_lock);
}
}
Expand Down Expand Up @@ -2689,29 +2695,36 @@ read_vhost_message(struct virtio_net *dev, int sockfd, struct vhu_msg_context *

ret = read_fd_message(dev->ifname, sockfd, (char *)&ctx->msg, VHOST_USER_HDR_SIZE,
ctx->fds, VHOST_MEMORY_MAX_NREGIONS, &ctx->fd_num);
if (ret <= 0) {
return ret;
} else if (ret != VHOST_USER_HDR_SIZE) {
if (ret <= 0)
goto out;

if (ret != VHOST_USER_HDR_SIZE) {
VHOST_LOG_CONFIG(ERR, "(%s) Unexpected header size read\n", dev->ifname);
close_msg_fds(ctx);
return -1;
ret = -1;
goto out;
}

if (ctx->msg.size) {
if (ctx->msg.size > sizeof(ctx->msg.payload)) {
VHOST_LOG_CONFIG(ERR, "(%s) invalid msg size: %d\n",
dev->ifname, ctx->msg.size);
return -1;
ret = -1;
goto out;
}
ret = read(sockfd, &ctx->msg.payload, ctx->msg.size);
if (ret <= 0)
return ret;
goto out;
if (ret != (int)ctx->msg.size) {
VHOST_LOG_CONFIG(ERR, "(%s) read control message failed\n", dev->ifname);
return -1;
ret = -1;
goto out;
}
}

out:
if (ret <= 0)
close_msg_fds(ctx);

return ret;
}

Expand Down Expand Up @@ -2866,7 +2879,6 @@ vhost_user_msg_handler(int vid, int fd)
return -1;
}

ret = 0;
request = ctx.msg.request.master;
if (request > VHOST_USER_NONE && request < VHOST_USER_MAX &&
vhost_message_str[request]) {
Expand Down Expand Up @@ -3003,9 +3015,11 @@ vhost_user_msg_handler(int vid, int fd)
send_vhost_reply(dev, fd, &ctx);
} else if (ret == RTE_VHOST_MSG_RESULT_ERR) {
VHOST_LOG_CONFIG(ERR, "(%s) vhost message handling failed.\n", dev->ifname);
return -1;
ret = -1;
goto unlock;
}

ret = 0;
for (i = 0; i < dev->nr_vring; i++) {
struct vhost_virtqueue *vq = dev->virtqueue[i];
bool cur_ready = vq_is_ready(dev, vq);
Expand All @@ -3016,10 +3030,11 @@ vhost_user_msg_handler(int vid, int fd)
}
}

unlock:
if (unlock_required)
vhost_user_unlock_all_queue_pairs(dev);

if (!virtio_is_ready(dev))
if (ret != 0 || !virtio_is_ready(dev))
goto out;

/*
Expand All @@ -3046,7 +3061,7 @@ vhost_user_msg_handler(int vid, int fd)
}

out:
return 0;
return ret;
}

static int process_slave_message_reply(struct virtio_net *dev,
Expand Down
Loading