On Mon, Nov 03, 2025 at 11:16:29AM +0100, Stefano Brivio wrote:
...and, for consistency, rename 'bytes' to 'copy' in iov_to_buf().
Two commits ago, I changed vhost-user functions to use iov_from_buf() to copy only up to the size of source buffers, instead of using the size of the destination vhost-user buffers.
This change pads the rest with zeroes, which is not strictly needed, but looks definitely cleaner.
This seems like a useful thing, but maybe it would be clearer as a separate iov_memset() / iov_from_zero() rather than built into iov_from_buf().
Signed-off-by: Stefano Brivio
--- iov.c | 54 ++++++++++++++++++++++++++++++++++------------------- iov.h | 4 ++-- vu_common.c | 2 +- 3 files changed, 38 insertions(+), 22 deletions(-) diff --git a/iov.c b/iov.c index dc1b6b1..557be55 100644 --- a/iov.c +++ b/iov.c @@ -59,35 +59,51 @@ size_t iov_skip_bytes(const struct iovec *iov, size_t n, * @iov_cnt: Number of elements in the iovec array * @offset: Destination offset in iovec array * @buf: Source buffer - * @bytes: Bytes to copy + * @copy: Bytes to copy + * @fill: Bytes to zero-fill after copied bytes * - * Return: number of bytes copied + * Return: number of bytes filled, with data or zeroes */ size_t iov_from_buf(const struct iovec *iov, size_t iov_cnt, - size_t offset, const void *buf, size_t bytes) + size_t offset, const void *buf, size_t copy, size_t fill) { + size_t copied, filled; unsigned int i; - size_t copied;
- if (__builtin_constant_p(bytes) && iov_cnt && - offset <= iov[0].iov_len && bytes <= iov[0].iov_len - offset) { - memcpy((char *)iov[0].iov_base + offset, buf, bytes); + if (__builtin_constant_p(copy) && iov_cnt && + offset <= iov[0].iov_len && + (copy + fill) <= iov[0].iov_len - offset) { + memcpy((char *)iov[0].iov_base + offset, buf, copy); + memset((char *)iov[0].iov_base + offset + copy, 0, fill);
- return bytes; + return copy + fill; }
i = iov_skip_bytes(iov, iov_cnt, offset, &offset);
- for (copied = 0; copied < bytes && i < iov_cnt; i++) { - size_t len = MIN(iov[i].iov_len - offset, bytes - copied); + for (copied = 0; copied < copy && i < iov_cnt; i++) { + size_t len = MIN(iov[i].iov_len - offset, copy - copied);
memcpy((char *)iov[i].iov_base + offset, (char *)buf + copied, len); copied += len; + + if (copied < copy) + offset = 0; /* More to copy in the next iteration */ + else + offset = len; /* Start of zero-filling, see below */ + } + + for (filled = 0; filled < fill && i < iov_cnt; i++) { + size_t len = MIN(iov[i].iov_len - offset, fill - filled); + + memcpy((char *)iov[i].iov_base + offset, + (char *)buf + copied + filled, len); + filled += len; offset = 0; }
- return copied; + return copied + filled; }
/** @@ -96,27 +112,27 @@ size_t iov_from_buf(const struct iovec *iov, size_t iov_cnt, * @iov_cnt: Number of elements in iovec array * @offset: Source offset altogether, counted in flattened iovec * @buf: Destination buffer - * @bytes: Bytes to copy + * @copy: Bytes to copy * * Return: number of bytes copied */ size_t iov_to_buf(const struct iovec *iov, size_t iov_cnt, - size_t offset, void *buf, size_t bytes) + size_t offset, void *buf, size_t copy) { unsigned int i; size_t copied;
- if (__builtin_constant_p(bytes) && iov_cnt && - offset <= iov[0].iov_len && bytes <= iov[0].iov_len - offset) { - memcpy(buf, (char *)iov[0].iov_base + offset, bytes); + if (__builtin_constant_p(copy) && iov_cnt && + offset <= iov[0].iov_len && copy <= iov[0].iov_len - offset) { + memcpy(buf, (char *)iov[0].iov_base + offset, copy);
- return bytes; + return copy; }
i = iov_skip_bytes(iov, iov_cnt, offset, &offset);
- for (copied = 0; copied < bytes && i < iov_cnt; i++) { - size_t len = MIN(iov[i].iov_len - offset, bytes - copied); + for (copied = 0; copied < copy && i < iov_cnt; i++) { + size_t len = MIN(iov[i].iov_len - offset, copy - copied);
ASSERT(iov[i].iov_base);
diff --git a/iov.h b/iov.h index ba1fda5..9b5d910 100644 --- a/iov.h +++ b/iov.h @@ -24,9 +24,9 @@ size_t iov_skip_bytes(const struct iovec *iov, size_t n, size_t skip, size_t *offset); size_t iov_from_buf(const struct iovec *iov, size_t iov_cnt, - size_t offset, const void *buf, size_t bytes); + size_t offset, const void *buf, size_t copy, size_t fill); size_t iov_to_buf(const struct iovec *iov, size_t iov_cnt, - size_t offset, void *buf, size_t bytes); + size_t offset, void *buf, size_t copy); size_t iov_size(const struct iovec *iov, size_t iov_cnt);
/* diff --git a/vu_common.c b/vu_common.c index 21cfb2a..d941b72 100644 --- a/vu_common.c +++ b/vu_common.c @@ -274,7 +274,7 @@ int vu_send_single(const struct ctx *c, const void *buf, size_t size)
/* copy data from the buffer to the iovec */ iov_from_buf(in_sg, elem_cnt, sizeof(struct virtio_net_hdr_mrg_rxbuf), - buf, size); + buf, size, vu_buf_size - size);
if (*c->pcap) { pcap_iov(in_sg, elem_cnt, -- 2.43.0
-- David Gibson (he or they) | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you, not the other way | around. http://www.ozlabs.org/~dgibson