On Fri, Apr 11, 2025 at 03:10:12PM +0200, Laurent Vivier wrote: > iov_tail_drop() discards a header from the iov_tail, > > iov_slice() makes a new iov referencing a subset of the data > in the original iov. > > Signed-off-by: Laurent Vivier Reviewed-by: David Gibson For the actual behaviour, couple of cosmetic nits noted below. > --- > iov.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > iov.h | 4 ++++ > 2 files changed, 72 insertions(+) > > diff --git a/iov.c b/iov.c > index 8c63b7ea6e31..d2aca59e42ed 100644 > --- a/iov.c > +++ b/iov.c > @@ -156,6 +156,59 @@ size_t iov_size(const struct iovec *iov, size_t iov_cnt) > return len; > } > > +/** > + * iov_slice - Make a new iov referencing a subset of the data in the original iov > + * > + * @dst_iov: Pointer to the destination array of struct iovec describing > + * the scatter/gather I/O vector to copy to. > + * @dst_iov_cnt: Maximum number of elements in the destination iov array. > + * @iov: Pointer to the source array of struct iovec describing > + * the scatter/gather I/O vector to copy from. > + * @iov_cnt: Maximum number of elements in the source iov array. > + * @offset: Offset within the source iov from where copying should start. > + * @bytes: On input, total number of bytes to copy from @iov to @dst_iov, > + * if @bytes is NULL, copy all the content of @iov, > + * on output actual number of bytes copied. > + * > + * Returns: The number of elements successfully copied to the destination > + * iov array, a negative value if there is no enough room in the s/no/not/ > + * destination iov array > + */ > +/* cppcheck-suppress unusedFunction */ > +int iov_slice(struct iovec *dst_iov, size_t dst_iov_cnt, > + const struct iovec *iov, size_t iov_cnt, > + size_t offset, size_t *bytes) > +{ > + unsigned int i, j; > + size_t remaining = bytes ? *bytes : SIZE_MAX; > + > + i = iov_skip_bytes(iov, iov_cnt, offset, &offset); > + > + /* copying data */ I think this comment is still a bit misleading. > + for (j = 0; i < iov_cnt && j < dst_iov_cnt && remaining; i++) { > + size_t len = MIN(remaining, iov[i].iov_len - offset); > + > + dst_iov[j].iov_base = (char *)iov[i].iov_base + offset; > + dst_iov[j].iov_len = len; > + j++; > + remaining -= len; > + offset = 0; > + } > + if (j == dst_iov_cnt) { > + if (bytes) { > + if (remaining) > + return -1; > + } else if (i != iov_cnt) { > + return -1; > + } > + } > + > + if (bytes) > + *bytes -= remaining; > + > + return j; > +} > + > /** > * iov_tail_prune() - Remove any unneeded buffers from an IOV tail > * @tail: IO vector tail (modified) > @@ -191,6 +244,21 @@ size_t iov_tail_size(struct iov_tail *tail) > return iov_size(tail->iov, tail->cnt) - tail->off; > } > > +/** > + * iov_tail_drop() - Discard a header from an IOV tail > + * @tail: IO vector tail > + * @len: length to move the head of the tail > + * > + * Returns: true if the tail still contains any bytes, otherwise false > + */ > +/* cppcheck-suppress unusedFunction */ > +bool iov_tail_drop(struct iov_tail *tail, size_t len) > +{ > + tail->off = tail->off + len; > + > + return iov_tail_prune(tail); > +} > + > /** > * iov_peek_header_() - Get pointer to a header from an IOV tail > * @tail: IOV tail to get header from > diff --git a/iov.h b/iov.h > index 9855bf0c0c32..3f8259aa8d28 100644 > --- a/iov.h > +++ b/iov.h > @@ -28,6 +28,9 @@ size_t iov_from_buf(const struct iovec *iov, size_t iov_cnt, > size_t iov_to_buf(const struct iovec *iov, size_t iov_cnt, > size_t offset, void *buf, size_t bytes); > size_t iov_size(const struct iovec *iov, size_t iov_cnt); > +int iov_slice(struct iovec *dst_iov, size_t dst_iov_cnt, > + const struct iovec *iov, size_t iov_cnt, > + size_t offset, size_t *bytes); > > /* > * DOC: Theory of Operation, struct iov_tail > @@ -72,6 +75,7 @@ struct iov_tail { > > bool iov_tail_prune(struct iov_tail *tail); > size_t iov_tail_size(struct iov_tail *tail); > +bool iov_tail_drop(struct iov_tail *tail, size_t len); > void *iov_peek_header_(struct iov_tail *tail, size_t len, size_t align); > void *iov_remove_header_(struct iov_tail *tail, size_t len, size_t align); > -- 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