From: Laurent Vivier <lvivier@redhat.com>
To: passt-dev@passt.top
Cc: Laurent Vivier <lvivier@redhat.com>
Subject: [PATCH 1/3] virtio: Pass iovec arrays as separate parameters to vu_queue_pop()
Date: Fri, 13 Mar 2026 08:21:34 +0100 [thread overview]
Message-ID: <20260313072136.4075535-2-lvivier@redhat.com> (raw)
In-Reply-To: <20260313072136.4075535-1-lvivier@redhat.com>
Currently vu_queue_pop() and vu_queue_map_desc() read the iovec arrays
(in_sg/out_sg) and their sizes (in_num/out_num) from the vu_virtq_element
struct. This couples the iovec storage to the element, requiring callers
like vu_handle_tx() to pre-initialize the element fields before calling
vu_queue_pop().
Pass the iovec arrays and their maximum sizes as separate parameters
instead. vu_queue_map_desc() now writes the actual descriptor count
and iovec pointers back into the element after mapping, rather than
using the element as both input and output.
This decouples the iovec storage from the element, which is a
prerequisite for multi-buffer support where a single frame can span
multiple virtqueue elements sharing a common iovec pool.
No functional change.
Signed-off-by: Laurent Vivier <lvivier@redhat.com>
---
virtio.c | 29 ++++++++++++++++++++++-------
virtio.h | 4 +++-
vu_common.c | 14 +++++++-------
3 files changed, 32 insertions(+), 15 deletions(-)
diff --git a/virtio.c b/virtio.c
index 447137ee83dd..a671163c27a0 100644
--- a/virtio.c
+++ b/virtio.c
@@ -428,12 +428,18 @@ static bool virtqueue_map_desc(const struct vu_dev *dev,
* @vq: Virtqueue
* @idx: First descriptor ring entry to map
* @elem: Virtqueue element to store descriptor ring iov
+ * @in_sg: Incoming iovec array for device-writable descriptors
+ * @max_in_sg: Maximum number of entries in @in_sg
+ * @out_sg: Outgoing iovec array for device-readable descriptors
+ * @max_out_sg: Maximum number of entries in @out_sg
*
* Return: -1 if there is an error, 0 otherwise
*/
static int vu_queue_map_desc(const struct vu_dev *dev,
struct vu_virtq *vq, unsigned int idx,
- struct vu_virtq_element *elem)
+ struct vu_virtq_element *elem,
+ struct iovec *in_sg, size_t max_in_sg,
+ struct iovec *out_sg, size_t max_out_sg)
{
const struct vring_desc *desc = vq->vring.desc;
struct vring_desc desc_buf[VIRTQUEUE_MAX_SIZE];
@@ -470,16 +476,16 @@ static int vu_queue_map_desc(const struct vu_dev *dev,
/* Collect all the descriptors */
do {
if (le16toh(desc[i].flags) & VRING_DESC_F_WRITE) {
- if (!virtqueue_map_desc(dev, &in_num, elem->in_sg,
- elem->in_num,
+ if (!virtqueue_map_desc(dev, &in_num, in_sg,
+ max_in_sg,
le64toh(desc[i].addr),
le32toh(desc[i].len)))
return -1;
} else {
if (in_num)
die("Incorrect order for descriptors");
- if (!virtqueue_map_desc(dev, &out_num, elem->out_sg,
- elem->out_num,
+ if (!virtqueue_map_desc(dev, &out_num, out_sg,
+ max_out_sg,
le64toh(desc[i].addr),
le32toh(desc[i].len))) {
return -1;
@@ -496,7 +502,9 @@ static int vu_queue_map_desc(const struct vu_dev *dev,
die("vhost-user: Failed to read descriptor list");
elem->index = idx;
+ elem->in_sg = in_sg;
elem->in_num = in_num;
+ elem->out_sg = out_sg;
elem->out_num = out_num;
return 0;
@@ -507,11 +515,17 @@ static int vu_queue_map_desc(const struct vu_dev *dev,
* @dev: Vhost-user device
* @vq: Virtqueue
* @elem: Virtqueue element to fill with the entry information
+ * @in_sg: Incoming iovec array for device-writable descriptors
+ * @max_in_sg: Maximum number of entries in @in_sg
+ * @out_sg: Outgoing iovec array for device-readable descriptors
+ * @max_out_sg: Maximum number of entries in @out_sg
*
* Return: -1 if there is an error, 0 otherwise
*/
int vu_queue_pop(const struct vu_dev *dev, struct vu_virtq *vq,
- struct vu_virtq_element *elem)
+ struct vu_virtq_element *elem,
+ struct iovec *in_sg, size_t max_in_sg,
+ struct iovec *out_sg, size_t max_out_sg)
{
unsigned int head;
int ret;
@@ -535,7 +549,8 @@ int vu_queue_pop(const struct vu_dev *dev, struct vu_virtq *vq,
if (vu_has_feature(dev, VIRTIO_RING_F_EVENT_IDX))
vring_set_avail_event(vq, vq->last_avail_idx);
- ret = vu_queue_map_desc(dev, vq, head, elem);
+ ret = vu_queue_map_desc(dev, vq, head, elem, in_sg, max_in_sg,
+ out_sg, max_out_sg);
if (ret < 0)
return ret;
diff --git a/virtio.h b/virtio.h
index d04bbe84e5c4..c7e447d59860 100644
--- a/virtio.h
+++ b/virtio.h
@@ -188,7 +188,9 @@ static inline bool vu_has_protocol_feature(const struct vu_dev *vdev,
void vu_queue_notify(const struct vu_dev *dev, struct vu_virtq *vq);
int vu_queue_pop(const struct vu_dev *dev, struct vu_virtq *vq,
- struct vu_virtq_element *elem);
+ struct vu_virtq_element *elem,
+ struct iovec *in_sg, size_t max_in_sg,
+ struct iovec *out_sg, size_t max_out_sg);
void vu_queue_detach_element(struct vu_virtq *vq);
void vu_queue_unpop(struct vu_virtq *vq);
bool vu_queue_rewind(struct vu_virtq *vq, unsigned int num);
diff --git a/vu_common.c b/vu_common.c
index 5f2ce18e5b71..4d809ac38a4b 100644
--- a/vu_common.c
+++ b/vu_common.c
@@ -91,7 +91,11 @@ int vu_collect(const struct vu_dev *vdev, struct vu_virtq *vq,
struct iovec *iov;
int ret;
- ret = vu_queue_pop(vdev, vq, &elem[elem_cnt]);
+ ret = vu_queue_pop(vdev, vq, &elem[elem_cnt],
+ elem[elem_cnt].in_sg,
+ elem[elem_cnt].in_num,
+ elem[elem_cnt].out_sg,
+ elem[elem_cnt].out_num);
if (ret < 0)
break;
@@ -178,12 +182,8 @@ static void vu_handle_tx(struct vu_dev *vdev, int index,
int ret;
struct iov_tail data;
- elem[count].out_num = VU_MAX_TX_BUFFER_NB;
- elem[count].out_sg = &out_sg[out_sg_count];
- elem[count].in_num = 0;
- elem[count].in_sg = NULL;
-
- ret = vu_queue_pop(vdev, vq, &elem[count]);
+ ret = vu_queue_pop(vdev, vq, &elem[count], NULL, 0,
+ &out_sg[out_sg_count], VU_MAX_TX_BUFFER_NB);
if (ret < 0)
break;
out_sg_count += elem[count].out_num;
--
2.53.0
next prev parent reply other threads:[~2026-03-13 7:21 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-13 7:21 [PATCH 0/3] Decouple iovec management from virtqueue elements Laurent Vivier
2026-03-13 7:21 ` Laurent Vivier [this message]
2026-03-13 7:21 ` [PATCH 2/3] vu_handle_tx: Pass actual remaining out_sg capacity to vu_queue_pop() Laurent Vivier
2026-03-13 7:21 ` [PATCH 3/3] vu_common: Move iovec management into vu_collect() Laurent Vivier
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=20260313072136.4075535-2-lvivier@redhat.com \
--to=lvivier@redhat.com \
--cc=passt-dev@passt.top \
/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.
Code repositories for project(s) associated with this public inbox
https://passt.top/passt
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 IMAP folder(s).