From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: passt.top; dmarc=none (p=none dis=none) header.from=gibson.dropbear.id.au Authentication-Results: passt.top; dkim=pass (2048-bit key; secure) header.d=gibson.dropbear.id.au header.i=@gibson.dropbear.id.au header.a=rsa-sha256 header.s=202504 header.b=i9JDsShz; dkim-atps=neutral Received: from mail.ozlabs.org (gandalf.ozlabs.org [150.107.74.76]) by passt.top (Postfix) with ESMTPS id D9B635A0276 for ; Wed, 16 Apr 2025 07:55:26 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gibson.dropbear.id.au; s=202504; t=1744782922; bh=9mzg2A/aKUPDsJ+NtLXeWxifyJRN5/4VYUDX+4mKn3U=; h=Date:From:To:Cc:Subject:References:In-Reply-To:From; b=i9JDsShzH8SRWIbcuLLgQdAOdrlxojywNb1HhIGPIAiWgGxnDoaXFpqzZYpa1+7cB geB8un0rkD6ikUCTE8KrB0WrglSvZ/hKXYpOPkmj0OSaF1fKOR/4ZV9LQoIRtZTybm LTiJKlCXc1Fe5fUJdhG0smA00aXYQ8XRjSiMhjX2Ed1obQpnqOo8W/GGZdK5wKbdUF XoLpulwJNHjwKfBmW5dmWVStMwCyiKJM+mHMLlbj13+zkGrZD0ytFOtIoy64LTC3rq j/6jWBJcNacO+ErQKEhgk5pfv0dl+PA4yIECL1TlFWR3YyBNsnV0Dib56ew75XU8LW QNFNcDdGAFj1w== Received: by gandalf.ozlabs.org (Postfix, from userid 1007) id 4Zcqxk2zW8z4xQ4; Wed, 16 Apr 2025 15:55:22 +1000 (AEST) Date: Wed, 16 Apr 2025 13:03:22 +1000 From: David Gibson To: Laurent Vivier Subject: Re: [PATCH v3 02/20] iov: Introduce iov_slice(), iov_tail_slice() and iov_tail_drop(). Message-ID: References: <20250415094300.65794-1-lvivier@redhat.com> <20250415094300.65794-3-lvivier@redhat.com> MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha256; protocol="application/pgp-signature"; boundary="COH/Uvpbdu4WIiSX" Content-Disposition: inline In-Reply-To: <20250415094300.65794-3-lvivier@redhat.com> Message-ID-Hash: 5TGXM5UUIUNURKTDPO3H7F2RSG6VVZAT X-Message-ID-Hash: 5TGXM5UUIUNURKTDPO3H7F2RSG6VVZAT X-MailFrom: dgibson@gandalf.ozlabs.org X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: passt-dev@passt.top X-Mailman-Version: 3.3.8 Precedence: list List-Id: Development discussion and patches for passt Archived-At: Archived-At: List-Archive: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: --COH/Uvpbdu4WIiSX Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable On Tue, Apr 15, 2025 at 11:42:42AM +0200, Laurent Vivier wrote: > iov_tail_drop() discards a header from the iov_tail, >=20 > iov_slice() makes a new iov referencing a subset of the data > in the original iov. >=20 > iov_tail_slice() is a wrapper for iov_slice() using iov_tail >=20 > Signed-off-by: Laurent Vivier > --- > iov.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > iov.h | 6 ++++ > 2 files changed, 98 insertions(+) >=20 > diff --git a/iov.c b/iov.c > index 8c63b7ea6e31..60ab1f9af973 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; > } > =20 > +/** > + * iov_slice - Make a new iov referencing a subset of the data in the o= riginal iov > + * > + * @dst_iov: Pointer to the destination array of struct iovec descri= bing > + * the scatter/gather I/O vector to copy to. The indentation seems a bit wonky here, looks like some lines are using spaces and others tabs. > + * @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_io= v, > + * 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 desti= nation > + * iov array, a negative value if there is not enough room in the > + * destination iov array > + */ > +/* cppcheck-suppress staticFunction */ > +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) The return value, is (usually) an iov count. Since that's given as a size_t in most places, it probably makes sense to use an ssize_t in the return value, rather than plain int. > +{ > + unsigned int i, j; > + size_t remaining =3D bytes ? *bytes : SIZE_MAX; > + > + i =3D iov_skip_bytes(iov, iov_cnt, offset, &offset); > + > + /* create a new iov array referencing a subset of the source one */ > + for (j =3D 0; i < iov_cnt && j < dst_iov_cnt && remaining; i++) { > + size_t len =3D MIN(remaining, iov[i].iov_len - offset); > + > + dst_iov[j].iov_base =3D (char *)iov[i].iov_base + offset; > + dst_iov[j].iov_len =3D len; > + j++; > + remaining -=3D len; > + offset =3D 0; > + } > + if (j =3D=3D dst_iov_cnt) { > + if (bytes) { > + if (remaining) > + return -1; > + } else if (i !=3D iov_cnt) { > + return -1; > + } > + } > + > + if (bytes) > + *bytes -=3D 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; > } > =20 > +/** > + * 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 =3D 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 > @@ -247,3 +315,27 @@ void *iov_remove_header_(struct iov_tail *tail, size= _t len, size_t align) > tail->off =3D tail->off + len; > return p; > } > + > +/** > + * iov_tail_slice - Make a new iov referencing a subset of the data > + * in an iov_tail > + * > + * @dst_iov: Pointer to the destination array of struct iovec descri= bing > + * the scatter/gather I/O vector to copy to. > + * @dst_iov_cnt: Maximum number of elements in the destination iov array. > + * @tail: Pointer to the source iov_tail > + * @bytes: On input, total number of bytes to copy from @iov to @dst_io= v, > + * if @bytes is NULL, copy all the content of @iov, > + * on output actual number of bytes copied. Do you have any use cases that need this parameter? The ones I remember from v2 all wanted to copy the entire remainder of the iov_tail. > + * Returns: The number of elements successfully copied to the desti= nation > + * iov array, a negative value if there is not enough room in the > + * destination iov array > + */ > +/* cppcheck-suppress unusedFunction */ > +int iov_tail_slice(struct iovec *dst_iov, size_t dst_iov_cnt, > + struct iov_tail *tail, size_t *bytes) > +{ > + return iov_slice(dst_iov, dst_iov_cnt, &tail->iov[0], tail->cnt, > + tail->off, bytes); > +} > diff --git a/iov.h b/iov.h > index 9855bf0c0c32..4bbdbf23f27b 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); > =20 > /* > * DOC: Theory of Operation, struct iov_tail > @@ -72,8 +75,11 @@ struct iov_tail { > =20 > 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= ); > +int iov_tail_slice(struct iovec *dst_iov, size_t dst_iov_cnt, > + struct iov_tail *tail, size_t *bytes); > =20 > /** > * IOV_PEEK_HEADER() - Get typed pointer to a header from an IOV tail --=20 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 --COH/Uvpbdu4WIiSX Content-Type: application/pgp-signature; name=signature.asc -----BEGIN PGP SIGNATURE----- iQIzBAEBCAAdFiEEO+dNsU4E3yXUXRK2zQJF27ox2GcFAmf/HfkACgkQzQJF27ox 2GdQrhAAjq/OXgEP4mqXiTzpE6QU5dV2RoEv9A/QC694/au24x4tYBy5ZlEh/HNh BH7OIA6a+c/FMr0Lj9l3YZ94If+JFwHPC/0ahEl5r7gvRCyhxFHw8en5IwvCZQ1c HOpgOrilisTZk9zVP7J/j52ro7ZVDsKSQkcfLEFQkTU1xWxTvC2qJz+IGi8HmWgW X1lG+8lgJ2LsGtNQS94h4FvsdKS3gU2r4U+0+8xzwdcIJNnhiktE88PP3Lawc/Xe tsSmYI404xXDb9OqokKVPmUNaChDuokvgcjdToDDPlqFkFRvNsLqLJMyjijbFwBh lEYCb+diFsHY5lWvEVeT5fpsUST/1lz0JybLyeD7Y35ciR9qp5E6XXkXA0JTrBGh BohRy64EMyyOAjWo+Jnd1Go62D1YuiimROrvNUJSyNDsykilVSjvii0o20huRlRt 35k4aPwdDsmf/qAUoPPJgNN5661ktJRrcqVtD0QqId7AzM2gDWYRC3EqDvGJayRV V6WrSYZbs/nxwwEhOE9sNI987hUqJeuPayPvzfamA2q+61qXgam3rBPxdUweVvRb Mm+lqaMM+YHRbpk1DZAVnsmiMQUv5jeHaSe4Ls70C7t9NwCdLMZfm3W+Q9ZQKb5j JPjQEKvHZl5wwLbZgIXQeZGpOmcjuxIO9AVmnqDjERp5hgv2UQM= =x5dK -----END PGP SIGNATURE----- --COH/Uvpbdu4WIiSX--