Message ID | 1354740430-22452-8-git-send-email-stefanha@redhat.com |
---|---|
State | New |
Headers | show |
On Wed, Dec 05, 2012 at 09:47:06PM +0100, Stefan Hajnoczi wrote: > The iov_discard() function removes data from the front or back of the > vector. This is useful when peeling off header/footer structs. > > Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> > --- > iov.c | 41 +++++++++++++++++++++++++++++++++++++++++ > iov.h | 13 +++++++++++++ > 2 files changed, 54 insertions(+) > > diff --git a/iov.c b/iov.c > index a81eedc..6eed089 100644 > --- a/iov.c > +++ b/iov.c > @@ -354,3 +354,44 @@ size_t qemu_iovec_memset(QEMUIOVector *qiov, size_t offset, > { > return iov_memset(qiov->iov, qiov->niov, offset, fillc, bytes); > } > + > +size_t iov_discard(struct iovec **iov, unsigned int *iov_cnt, ssize_t bytes) > +{ > + size_t total = 0; > + struct iovec *cur; > + int direction; > + > + if (*iov_cnt == 0) { > + return 0; > + } > + > + if (bytes < 0) { > + bytes = -bytes; > + direction = -1; > + cur = *iov + (*iov_cnt - 1); > + } else { > + direction = 1; > + cur = *iov; > + } > + > + while (*iov_cnt > 0) { > + if (cur->iov_len > bytes) { > + if (direction > 0) { > + cur->iov_base += bytes; > + } > + cur->iov_len -= bytes; > + total += bytes; > + break; > + } > + > + bytes -= cur->iov_len; > + total += cur->iov_len; > + cur += direction; > + *iov_cnt -= 1; > + } > + > + if (direction > 0) { > + *iov = cur; > + } > + return total; > +} > diff --git a/iov.h b/iov.h > index 34c8ec9..d6d1fa6 100644 > --- a/iov.h > +++ b/iov.h > @@ -95,3 +95,16 @@ void iov_hexdump(const struct iovec *iov, const unsigned int iov_cnt, > unsigned iov_copy(struct iovec *dst_iov, unsigned int dst_iov_cnt, > const struct iovec *iov, unsigned int iov_cnt, > size_t offset, size_t bytes); > + > +/* > + * Remove a given number of bytes from the front or back of a vector. > + * This may update iov and/or iov_cnt to exclude iovec elements that are > + * no longer required. > + * > + * Data is discarded from the front of the vector if bytes is positive and > + * from the back of the vector if bytes is negative. I think I already commented on this: I think this interface is too tricky, and use of ssize_t is a bad idea since most of code uses size_t: you might start getting integer overflow errors if you convert. Better to have size_t iov_discard_front(struct iovec **iov, unsigned int *iov_cnt, ssize_t bytes); size_t iov_discard_back(struct iovec **iov, unsigned int *iov_cnt, ssize_t bytes); which explicitly do the right thing. The fix up users to use size_t everywhere. > + * > + * The number of bytes actually discarded is returned. This number may be > + * smaller than requested if the vector is too small. > + */ > +size_t iov_discard(struct iovec **iov, unsigned int *iov_cnt, ssize_t bytes); > -- > 1.8.0.1
On Thu, Dec 06, 2012 at 01:36:42PM +0200, Michael S. Tsirkin wrote: > On Wed, Dec 05, 2012 at 09:47:06PM +0100, Stefan Hajnoczi wrote: > > The iov_discard() function removes data from the front or back of the > > vector. This is useful when peeling off header/footer structs. > > > > Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> > > --- > > iov.c | 41 +++++++++++++++++++++++++++++++++++++++++ > > iov.h | 13 +++++++++++++ > > 2 files changed, 54 insertions(+) > > > > diff --git a/iov.c b/iov.c > > index a81eedc..6eed089 100644 > > --- a/iov.c > > +++ b/iov.c > > @@ -354,3 +354,44 @@ size_t qemu_iovec_memset(QEMUIOVector *qiov, size_t offset, > > { > > return iov_memset(qiov->iov, qiov->niov, offset, fillc, bytes); > > } > > + > > +size_t iov_discard(struct iovec **iov, unsigned int *iov_cnt, ssize_t bytes) > > +{ > > + size_t total = 0; > > + struct iovec *cur; > > + int direction; > > + > > + if (*iov_cnt == 0) { > > + return 0; > > + } > > + > > + if (bytes < 0) { > > + bytes = -bytes; > > + direction = -1; > > + cur = *iov + (*iov_cnt - 1); > > + } else { > > + direction = 1; > > + cur = *iov; > > + } > > + > > + while (*iov_cnt > 0) { > > + if (cur->iov_len > bytes) { > > + if (direction > 0) { > > + cur->iov_base += bytes; > > + } > > + cur->iov_len -= bytes; > > + total += bytes; > > + break; > > + } > > + > > + bytes -= cur->iov_len; > > + total += cur->iov_len; > > + cur += direction; > > + *iov_cnt -= 1; > > + } > > + > > + if (direction > 0) { > > + *iov = cur; > > + } > > + return total; > > +} > > diff --git a/iov.h b/iov.h > > index 34c8ec9..d6d1fa6 100644 > > --- a/iov.h > > +++ b/iov.h > > @@ -95,3 +95,16 @@ void iov_hexdump(const struct iovec *iov, const unsigned int iov_cnt, > > unsigned iov_copy(struct iovec *dst_iov, unsigned int dst_iov_cnt, > > const struct iovec *iov, unsigned int iov_cnt, > > size_t offset, size_t bytes); > > + > > +/* > > + * Remove a given number of bytes from the front or back of a vector. > > + * This may update iov and/or iov_cnt to exclude iovec elements that are > > + * no longer required. > > + * > > + * Data is discarded from the front of the vector if bytes is positive and > > + * from the back of the vector if bytes is negative. > > I think I already commented on this: I think this interface is too tricky, > and use of ssize_t is a bad idea since most of code uses size_t: > you might start getting integer overflow errors if you convert. > > Better to have > size_t iov_discard_front(struct iovec **iov, unsigned int *iov_cnt, ssize_t bytes); > size_t iov_discard_back(struct iovec **iov, unsigned int *iov_cnt, ssize_t bytes); > > which explicitly do the right thing. > > The fix up users to use size_t everywhere. Okay, will split into front/back. Stefan
diff --git a/iov.c b/iov.c index a81eedc..6eed089 100644 --- a/iov.c +++ b/iov.c @@ -354,3 +354,44 @@ size_t qemu_iovec_memset(QEMUIOVector *qiov, size_t offset, { return iov_memset(qiov->iov, qiov->niov, offset, fillc, bytes); } + +size_t iov_discard(struct iovec **iov, unsigned int *iov_cnt, ssize_t bytes) +{ + size_t total = 0; + struct iovec *cur; + int direction; + + if (*iov_cnt == 0) { + return 0; + } + + if (bytes < 0) { + bytes = -bytes; + direction = -1; + cur = *iov + (*iov_cnt - 1); + } else { + direction = 1; + cur = *iov; + } + + while (*iov_cnt > 0) { + if (cur->iov_len > bytes) { + if (direction > 0) { + cur->iov_base += bytes; + } + cur->iov_len -= bytes; + total += bytes; + break; + } + + bytes -= cur->iov_len; + total += cur->iov_len; + cur += direction; + *iov_cnt -= 1; + } + + if (direction > 0) { + *iov = cur; + } + return total; +} diff --git a/iov.h b/iov.h index 34c8ec9..d6d1fa6 100644 --- a/iov.h +++ b/iov.h @@ -95,3 +95,16 @@ void iov_hexdump(const struct iovec *iov, const unsigned int iov_cnt, unsigned iov_copy(struct iovec *dst_iov, unsigned int dst_iov_cnt, const struct iovec *iov, unsigned int iov_cnt, size_t offset, size_t bytes); + +/* + * Remove a given number of bytes from the front or back of a vector. + * This may update iov and/or iov_cnt to exclude iovec elements that are + * no longer required. + * + * Data is discarded from the front of the vector if bytes is positive and + * from the back of the vector if bytes is negative. + * + * The number of bytes actually discarded is returned. This number may be + * smaller than requested if the vector is too small. + */ +size_t iov_discard(struct iovec **iov, unsigned int *iov_cnt, ssize_t bytes);
The iov_discard() function removes data from the front or back of the vector. This is useful when peeling off header/footer structs. Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> --- iov.c | 41 +++++++++++++++++++++++++++++++++++++++++ iov.h | 13 +++++++++++++ 2 files changed, 54 insertions(+)