2010-04-27 14:34:05 +02:00
|
|
|
/*
|
rewrite iov_* functions
This changes implementations of all iov_*
functions, completing the previous step.
All iov_* functions now ensure that this offset
argument is within the iovec (using assertion),
but lets to specify `bytes' value larger than
actual length of the iovec - in this case they
stops at the actual end of iovec. It is also
suggested to use convinient `-1' value as `bytes'
to mean just this -- "up to the end".
There's one very minor semantic change here: new
requiriment is that `offset' points to inside of
iovec. This is checked just at the end of functions
(assert()), it does not actually need to be enforced,
but using any of these functions with offset pointing
past the end of iovec is wrong anyway.
Note: the new code in iov.c uses arithmetic with
void pointers. I thought this is not supported
everywhere and is a GCC extension (indeed, the C
standard does not define void arithmetic). However,
the original code already use void arith in
iov_from_buf() function:
(memcpy(..., buf + buf_off,...)
which apparently works well so far (it is this
way in qemu 1.0). So I left it this way and used
it in other places.
While at it, add a unit-test file test-iov.c,
to check various corner cases with iov_from_buf(),
iov_to_buf() and iov_memset().
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2012-06-07 18:08:19 +02:00
|
|
|
* Helpers for using (partial) iovecs.
|
2010-04-27 14:34:05 +02:00
|
|
|
*
|
|
|
|
* Copyright (C) 2010 Red Hat, Inc.
|
|
|
|
*
|
|
|
|
* Author(s):
|
|
|
|
* Amit Shah <amit.shah@redhat.com>
|
rewrite iov_* functions
This changes implementations of all iov_*
functions, completing the previous step.
All iov_* functions now ensure that this offset
argument is within the iovec (using assertion),
but lets to specify `bytes' value larger than
actual length of the iovec - in this case they
stops at the actual end of iovec. It is also
suggested to use convinient `-1' value as `bytes'
to mean just this -- "up to the end".
There's one very minor semantic change here: new
requiriment is that `offset' points to inside of
iovec. This is checked just at the end of functions
(assert()), it does not actually need to be enforced,
but using any of these functions with offset pointing
past the end of iovec is wrong anyway.
Note: the new code in iov.c uses arithmetic with
void pointers. I thought this is not supported
everywhere and is a GCC extension (indeed, the C
standard does not define void arithmetic). However,
the original code already use void arith in
iov_from_buf() function:
(memcpy(..., buf + buf_off,...)
which apparently works well so far (it is this
way in qemu 1.0). So I left it this way and used
it in other places.
While at it, add a unit-test file test-iov.c,
to check various corner cases with iov_from_buf(),
iov_to_buf() and iov_memset().
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2012-06-07 18:08:19 +02:00
|
|
|
* Michael Tokarev <mjt@tls.msk.ru>
|
2010-04-27 14:34:05 +02:00
|
|
|
*
|
|
|
|
* This work is licensed under the terms of the GNU GPL, version 2. See
|
|
|
|
* the COPYING file in the top-level directory.
|
|
|
|
*/
|
|
|
|
|
2012-12-06 12:15:58 +01:00
|
|
|
#ifndef IOV_H
|
|
|
|
#define IOV_H
|
|
|
|
|
change iov_* function prototypes to be more appropriate
Reorder arguments to be more natural, readable and
consistent with other iov_* functions, and change
argument names, from:
iov_from_buf(iov, iov_cnt, buf, iov_off, size)
to
iov_from_buf(iov, iov_cnt, offset, buf, bytes)
The result becomes natural English:
copy data to this `iov' vector with `iov_cnt'
elements starting at byte offset `offset'
from memory buffer `buf', processing `bytes'
bytes max.
(Try to read the original prototype this way).
Also change iov_clear() to more general iov_memset()
(it uses memset() internally anyway).
While at it, add comments to the header file
describing what the routines actually does.
The patch only renames argumens in the header, but
keeps old names in the implementation. The next
patch will touch actual code to match.
Now, it might look wrong to pay so much attention
to so small things. But we've so many badly designed
interfaces already so the whole thing becomes rather
confusing or error prone. One example of this is
previous commit and small discussion which emerged
from it, with an outcome that the utility functions
like these aren't well-understdandable, leading to
strange usage cases. That's why I paid quite some
attention to this set of functions and a few
others in subsequent patches.
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2012-03-11 15:05:12 +01:00
|
|
|
/**
|
|
|
|
* count and return data size, in bytes, of an iovec
|
|
|
|
* starting at `iov' of `iov_cnt' number of elements.
|
|
|
|
*/
|
|
|
|
size_t iov_size(const struct iovec *iov, const unsigned int iov_cnt);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Copy from single continuous buffer to scatter-gather vector of buffers
|
|
|
|
* (iovec) and back like memcpy() between two continuous memory regions.
|
|
|
|
* Data in single continuous buffer starting at address `buf' and
|
|
|
|
* `bytes' bytes long will be copied to/from an iovec `iov' with
|
|
|
|
* `iov_cnt' number of elements, starting at byte position `offset'
|
|
|
|
* within the iovec. If the iovec does not contain enough space,
|
|
|
|
* only part of data will be copied, up to the end of the iovec.
|
|
|
|
* Number of bytes actually copied will be returned, which is
|
|
|
|
* min(bytes, iov_size(iov)-offset)
|
rewrite iov_* functions
This changes implementations of all iov_*
functions, completing the previous step.
All iov_* functions now ensure that this offset
argument is within the iovec (using assertion),
but lets to specify `bytes' value larger than
actual length of the iovec - in this case they
stops at the actual end of iovec. It is also
suggested to use convinient `-1' value as `bytes'
to mean just this -- "up to the end".
There's one very minor semantic change here: new
requiriment is that `offset' points to inside of
iovec. This is checked just at the end of functions
(assert()), it does not actually need to be enforced,
but using any of these functions with offset pointing
past the end of iovec is wrong anyway.
Note: the new code in iov.c uses arithmetic with
void pointers. I thought this is not supported
everywhere and is a GCC extension (indeed, the C
standard does not define void arithmetic). However,
the original code already use void arith in
iov_from_buf() function:
(memcpy(..., buf + buf_off,...)
which apparently works well so far (it is this
way in qemu 1.0). So I left it this way and used
it in other places.
While at it, add a unit-test file test-iov.c,
to check various corner cases with iov_from_buf(),
iov_to_buf() and iov_memset().
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2012-06-07 18:08:19 +02:00
|
|
|
* `Offset' must point to the inside of iovec.
|
change iov_* function prototypes to be more appropriate
Reorder arguments to be more natural, readable and
consistent with other iov_* functions, and change
argument names, from:
iov_from_buf(iov, iov_cnt, buf, iov_off, size)
to
iov_from_buf(iov, iov_cnt, offset, buf, bytes)
The result becomes natural English:
copy data to this `iov' vector with `iov_cnt'
elements starting at byte offset `offset'
from memory buffer `buf', processing `bytes'
bytes max.
(Try to read the original prototype this way).
Also change iov_clear() to more general iov_memset()
(it uses memset() internally anyway).
While at it, add comments to the header file
describing what the routines actually does.
The patch only renames argumens in the header, but
keeps old names in the implementation. The next
patch will touch actual code to match.
Now, it might look wrong to pay so much attention
to so small things. But we've so many badly designed
interfaces already so the whole thing becomes rather
confusing or error prone. One example of this is
previous commit and small discussion which emerged
from it, with an outcome that the utility functions
like these aren't well-understdandable, leading to
strange usage cases. That's why I paid quite some
attention to this set of functions and a few
others in subsequent patches.
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2012-03-11 15:05:12 +01:00
|
|
|
*/
|
2015-12-22 12:03:33 +01:00
|
|
|
size_t iov_from_buf_full(const struct iovec *iov, unsigned int iov_cnt,
|
|
|
|
size_t offset, const void *buf, size_t bytes);
|
|
|
|
size_t iov_to_buf_full(const struct iovec *iov, const unsigned int iov_cnt,
|
2018-12-13 23:37:37 +01:00
|
|
|
size_t offset, void *buf, size_t bytes);
|
2015-12-22 12:03:33 +01:00
|
|
|
|
|
|
|
static inline size_t
|
|
|
|
iov_from_buf(const struct iovec *iov, unsigned int iov_cnt,
|
|
|
|
size_t offset, const void *buf, size_t bytes)
|
|
|
|
{
|
|
|
|
if (__builtin_constant_p(bytes) && iov_cnt &&
|
|
|
|
offset <= iov[0].iov_len && bytes <= iov[0].iov_len - offset) {
|
|
|
|
memcpy(iov[0].iov_base + offset, buf, bytes);
|
|
|
|
return bytes;
|
|
|
|
} else {
|
|
|
|
return iov_from_buf_full(iov, iov_cnt, offset, buf, bytes);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline size_t
|
|
|
|
iov_to_buf(const struct iovec *iov, const unsigned int iov_cnt,
|
|
|
|
size_t offset, void *buf, size_t bytes)
|
|
|
|
{
|
|
|
|
if (__builtin_constant_p(bytes) && iov_cnt &&
|
|
|
|
offset <= iov[0].iov_len && bytes <= iov[0].iov_len - offset) {
|
|
|
|
memcpy(buf, iov[0].iov_base + offset, bytes);
|
|
|
|
return bytes;
|
|
|
|
} else {
|
|
|
|
return iov_to_buf_full(iov, iov_cnt, offset, buf, bytes);
|
|
|
|
}
|
|
|
|
}
|
change iov_* function prototypes to be more appropriate
Reorder arguments to be more natural, readable and
consistent with other iov_* functions, and change
argument names, from:
iov_from_buf(iov, iov_cnt, buf, iov_off, size)
to
iov_from_buf(iov, iov_cnt, offset, buf, bytes)
The result becomes natural English:
copy data to this `iov' vector with `iov_cnt'
elements starting at byte offset `offset'
from memory buffer `buf', processing `bytes'
bytes max.
(Try to read the original prototype this way).
Also change iov_clear() to more general iov_memset()
(it uses memset() internally anyway).
While at it, add comments to the header file
describing what the routines actually does.
The patch only renames argumens in the header, but
keeps old names in the implementation. The next
patch will touch actual code to match.
Now, it might look wrong to pay so much attention
to so small things. But we've so many badly designed
interfaces already so the whole thing becomes rather
confusing or error prone. One example of this is
previous commit and small discussion which emerged
from it, with an outcome that the utility functions
like these aren't well-understdandable, leading to
strange usage cases. That's why I paid quite some
attention to this set of functions and a few
others in subsequent patches.
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2012-03-11 15:05:12 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Set data bytes pointed out by iovec `iov' of size `iov_cnt' elements,
|
|
|
|
* starting at byte offset `start', to value `fillc', repeating it
|
rewrite iov_* functions
This changes implementations of all iov_*
functions, completing the previous step.
All iov_* functions now ensure that this offset
argument is within the iovec (using assertion),
but lets to specify `bytes' value larger than
actual length of the iovec - in this case they
stops at the actual end of iovec. It is also
suggested to use convinient `-1' value as `bytes'
to mean just this -- "up to the end".
There's one very minor semantic change here: new
requiriment is that `offset' points to inside of
iovec. This is checked just at the end of functions
(assert()), it does not actually need to be enforced,
but using any of these functions with offset pointing
past the end of iovec is wrong anyway.
Note: the new code in iov.c uses arithmetic with
void pointers. I thought this is not supported
everywhere and is a GCC extension (indeed, the C
standard does not define void arithmetic). However,
the original code already use void arith in
iov_from_buf() function:
(memcpy(..., buf + buf_off,...)
which apparently works well so far (it is this
way in qemu 1.0). So I left it this way and used
it in other places.
While at it, add a unit-test file test-iov.c,
to check various corner cases with iov_from_buf(),
iov_to_buf() and iov_memset().
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2012-06-07 18:08:19 +02:00
|
|
|
* `bytes' number of times. `Offset' must point to the inside of iovec.
|
change iov_* function prototypes to be more appropriate
Reorder arguments to be more natural, readable and
consistent with other iov_* functions, and change
argument names, from:
iov_from_buf(iov, iov_cnt, buf, iov_off, size)
to
iov_from_buf(iov, iov_cnt, offset, buf, bytes)
The result becomes natural English:
copy data to this `iov' vector with `iov_cnt'
elements starting at byte offset `offset'
from memory buffer `buf', processing `bytes'
bytes max.
(Try to read the original prototype this way).
Also change iov_clear() to more general iov_memset()
(it uses memset() internally anyway).
While at it, add comments to the header file
describing what the routines actually does.
The patch only renames argumens in the header, but
keeps old names in the implementation. The next
patch will touch actual code to match.
Now, it might look wrong to pay so much attention
to so small things. But we've so many badly designed
interfaces already so the whole thing becomes rather
confusing or error prone. One example of this is
previous commit and small discussion which emerged
from it, with an outcome that the utility functions
like these aren't well-understdandable, leading to
strange usage cases. That's why I paid quite some
attention to this set of functions and a few
others in subsequent patches.
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2012-03-11 15:05:12 +01:00
|
|
|
* If `bytes' is large enough, only last bytes portion of iovec,
|
|
|
|
* up to the end of it, will be filled with the specified value.
|
|
|
|
* Function return actual number of bytes processed, which is
|
|
|
|
* min(size, iov_size(iov) - offset).
|
|
|
|
*/
|
|
|
|
size_t iov_memset(const struct iovec *iov, const unsigned int iov_cnt,
|
|
|
|
size_t offset, int fillc, size_t bytes);
|
|
|
|
|
rename qemu_sendv to iov_send, change proto and move declarations to iov.h
Rename arguments and use size_t for sizes instead of int,
from
int
qemu_sendv(int sockfd, struct iovec *iov,
int len, int iov_offset)
to
ssize_t
iov_send(int sockfd, struct iovec *iov,
size_t offset, size_t bytes)
The main motivation was to make it clear that length
and offset are in _bytes_, not in iov elements: it was
very confusing before, because all standard functions
which deals with iovecs expects number of iovs, not
bytes, even the fact that struct iovec has iov_len and
iov_ prefix does not help. With "bytes" and "offset",
especially since they're now size_t, it is much more
explicit. Also change the return type to be ssize_t
instead of int.
This also changes it to match other iov-related functons,
but not _quite_: there's still no argument indicating
where iovec ends, ie, no iov_cnt parameter as used
in iov_size() and friends. If will be added in subsequent
patch/rewrite.
All callers of qemu_sendv() and qemu_recvv() and
related, like qemu_co_sendv() and qemu_co_recvv(),
were checked to verify that it is safe to use unsigned
datatype instead of int.
Note that the order of arguments is changed to: offset
and bytes (len and iov_offset) are swapped with each
other. This is to make them consistent with very similar
functions from qemu_iovec family, where offset always
follows qiov, to mean the place in it to start from.
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2012-03-10 14:00:41 +01:00
|
|
|
/*
|
|
|
|
* Send/recv data from/to iovec buffers directly
|
|
|
|
*
|
|
|
|
* `offset' bytes in the beginning of iovec buffer are skipped and
|
|
|
|
* next `bytes' bytes are used, which must be within data of iovec.
|
|
|
|
*
|
2012-03-14 08:18:54 +01:00
|
|
|
* r = iov_send_recv(sockfd, iov, iovcnt, offset, bytes, true);
|
rename qemu_sendv to iov_send, change proto and move declarations to iov.h
Rename arguments and use size_t for sizes instead of int,
from
int
qemu_sendv(int sockfd, struct iovec *iov,
int len, int iov_offset)
to
ssize_t
iov_send(int sockfd, struct iovec *iov,
size_t offset, size_t bytes)
The main motivation was to make it clear that length
and offset are in _bytes_, not in iov elements: it was
very confusing before, because all standard functions
which deals with iovecs expects number of iovs, not
bytes, even the fact that struct iovec has iov_len and
iov_ prefix does not help. With "bytes" and "offset",
especially since they're now size_t, it is much more
explicit. Also change the return type to be ssize_t
instead of int.
This also changes it to match other iov-related functons,
but not _quite_: there's still no argument indicating
where iovec ends, ie, no iov_cnt parameter as used
in iov_size() and friends. If will be added in subsequent
patch/rewrite.
All callers of qemu_sendv() and qemu_recvv() and
related, like qemu_co_sendv() and qemu_co_recvv(),
were checked to verify that it is safe to use unsigned
datatype instead of int.
Note that the order of arguments is changed to: offset
and bytes (len and iov_offset) are swapped with each
other. This is to make them consistent with very similar
functions from qemu_iovec family, where offset always
follows qiov, to mean the place in it to start from.
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2012-03-10 14:00:41 +01:00
|
|
|
*
|
|
|
|
* is logically equivalent to
|
|
|
|
*
|
|
|
|
* char *buf = malloc(bytes);
|
|
|
|
* iov_to_buf(iov, iovcnt, offset, buf, bytes);
|
|
|
|
* r = send(sockfd, buf, bytes, 0);
|
|
|
|
* free(buf);
|
2012-03-14 08:18:54 +01:00
|
|
|
*
|
|
|
|
* For iov_send_recv() _whole_ area being sent or received
|
|
|
|
* should be within the iovec, not only beginning of it.
|
rename qemu_sendv to iov_send, change proto and move declarations to iov.h
Rename arguments and use size_t for sizes instead of int,
from
int
qemu_sendv(int sockfd, struct iovec *iov,
int len, int iov_offset)
to
ssize_t
iov_send(int sockfd, struct iovec *iov,
size_t offset, size_t bytes)
The main motivation was to make it clear that length
and offset are in _bytes_, not in iov elements: it was
very confusing before, because all standard functions
which deals with iovecs expects number of iovs, not
bytes, even the fact that struct iovec has iov_len and
iov_ prefix does not help. With "bytes" and "offset",
especially since they're now size_t, it is much more
explicit. Also change the return type to be ssize_t
instead of int.
This also changes it to match other iov-related functons,
but not _quite_: there's still no argument indicating
where iovec ends, ie, no iov_cnt parameter as used
in iov_size() and friends. If will be added in subsequent
patch/rewrite.
All callers of qemu_sendv() and qemu_recvv() and
related, like qemu_co_sendv() and qemu_co_recvv(),
were checked to verify that it is safe to use unsigned
datatype instead of int.
Note that the order of arguments is changed to: offset
and bytes (len and iov_offset) are swapped with each
other. This is to make them consistent with very similar
functions from qemu_iovec family, where offset always
follows qiov, to mean the place in it to start from.
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2012-03-10 14:00:41 +01:00
|
|
|
*/
|
2015-05-21 03:50:10 +02:00
|
|
|
ssize_t iov_send_recv(int sockfd, const struct iovec *iov, unsigned iov_cnt,
|
2012-03-14 07:56:04 +01:00
|
|
|
size_t offset, size_t bytes, bool do_send);
|
2012-03-14 08:18:54 +01:00
|
|
|
#define iov_recv(sockfd, iov, iov_cnt, offset, bytes) \
|
|
|
|
iov_send_recv(sockfd, iov, iov_cnt, offset, bytes, false)
|
|
|
|
#define iov_send(sockfd, iov, iov_cnt, offset, bytes) \
|
|
|
|
iov_send_recv(sockfd, iov, iov_cnt, offset, bytes, true)
|
rename qemu_sendv to iov_send, change proto and move declarations to iov.h
Rename arguments and use size_t for sizes instead of int,
from
int
qemu_sendv(int sockfd, struct iovec *iov,
int len, int iov_offset)
to
ssize_t
iov_send(int sockfd, struct iovec *iov,
size_t offset, size_t bytes)
The main motivation was to make it clear that length
and offset are in _bytes_, not in iov elements: it was
very confusing before, because all standard functions
which deals with iovecs expects number of iovs, not
bytes, even the fact that struct iovec has iov_len and
iov_ prefix does not help. With "bytes" and "offset",
especially since they're now size_t, it is much more
explicit. Also change the return type to be ssize_t
instead of int.
This also changes it to match other iov-related functons,
but not _quite_: there's still no argument indicating
where iovec ends, ie, no iov_cnt parameter as used
in iov_size() and friends. If will be added in subsequent
patch/rewrite.
All callers of qemu_sendv() and qemu_recvv() and
related, like qemu_co_sendv() and qemu_co_recvv(),
were checked to verify that it is safe to use unsigned
datatype instead of int.
Note that the order of arguments is changed to: offset
and bytes (len and iov_offset) are swapped with each
other. This is to make them consistent with very similar
functions from qemu_iovec family, where offset always
follows qiov, to mean the place in it to start from.
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2012-03-10 14:00:41 +01:00
|
|
|
|
change iov_* function prototypes to be more appropriate
Reorder arguments to be more natural, readable and
consistent with other iov_* functions, and change
argument names, from:
iov_from_buf(iov, iov_cnt, buf, iov_off, size)
to
iov_from_buf(iov, iov_cnt, offset, buf, bytes)
The result becomes natural English:
copy data to this `iov' vector with `iov_cnt'
elements starting at byte offset `offset'
from memory buffer `buf', processing `bytes'
bytes max.
(Try to read the original prototype this way).
Also change iov_clear() to more general iov_memset()
(it uses memset() internally anyway).
While at it, add comments to the header file
describing what the routines actually does.
The patch only renames argumens in the header, but
keeps old names in the implementation. The next
patch will touch actual code to match.
Now, it might look wrong to pay so much attention
to so small things. But we've so many badly designed
interfaces already so the whole thing becomes rather
confusing or error prone. One example of this is
previous commit and small discussion which emerged
from it, with an outcome that the utility functions
like these aren't well-understdandable, leading to
strange usage cases. That's why I paid quite some
attention to this set of functions and a few
others in subsequent patches.
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2012-03-11 15:05:12 +01:00
|
|
|
/**
|
|
|
|
* Produce a text hexdump of iovec `iov' with `iov_cnt' number of elements
|
|
|
|
* in file `fp', prefixing each line with `prefix' and processing not more
|
|
|
|
* than `limit' data bytes.
|
|
|
|
*/
|
2011-07-12 13:35:10 +02:00
|
|
|
void iov_hexdump(const struct iovec *iov, const unsigned int iov_cnt,
|
|
|
|
FILE *fp, const char *prefix, size_t limit);
|
2012-09-24 13:02:52 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Partial copy of vector from iov to dst_iov (data is not copied).
|
|
|
|
* dst_iov overlaps iov at a specified offset.
|
|
|
|
* size of dst_iov is at most bytes. dst vector count is returned.
|
|
|
|
*/
|
|
|
|
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);
|
2012-12-06 12:15:58 +01:00
|
|
|
|
2012-11-21 17:41:10 +01:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
* 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_front(struct iovec **iov, unsigned int *iov_cnt,
|
|
|
|
size_t bytes);
|
|
|
|
size_t iov_discard_back(struct iovec *iov, unsigned int *iov_cnt,
|
|
|
|
size_t bytes);
|
|
|
|
|
2020-09-17 11:44:53 +02:00
|
|
|
/* Information needed to undo an iov_discard_*() operation */
|
|
|
|
typedef struct {
|
|
|
|
struct iovec *modified_iov;
|
|
|
|
struct iovec orig;
|
|
|
|
} IOVDiscardUndo;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Undo an iov_discard_front_undoable() or iov_discard_back_undoable()
|
|
|
|
* operation. If multiple operations are made then each one needs a separate
|
|
|
|
* IOVDiscardUndo and iov_discard_undo() must be called in the reverse order
|
|
|
|
* that the operations were made.
|
|
|
|
*/
|
|
|
|
void iov_discard_undo(IOVDiscardUndo *undo);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Undoable versions of iov_discard_front() and iov_discard_back(). Use
|
|
|
|
* iov_discard_undo() to reset to the state before the discard operations.
|
|
|
|
*/
|
|
|
|
size_t iov_discard_front_undoable(struct iovec **iov, unsigned int *iov_cnt,
|
|
|
|
size_t bytes, IOVDiscardUndo *undo);
|
|
|
|
size_t iov_discard_back_undoable(struct iovec *iov, unsigned int *iov_cnt,
|
|
|
|
size_t bytes, IOVDiscardUndo *undo);
|
|
|
|
|
2016-03-09 10:52:44 +01:00
|
|
|
typedef struct QEMUIOVector {
|
|
|
|
struct iovec *iov;
|
|
|
|
int niov;
|
2019-02-18 15:09:10 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* For external @iov (qemu_iovec_init_external()) or allocated @iov
|
|
|
|
* (qemu_iovec_init()), @size is the cumulative size of iovecs and
|
|
|
|
* @local_iov is invalid and unused.
|
|
|
|
*
|
|
|
|
* For embedded @iov (QEMU_IOVEC_INIT_BUF() or qemu_iovec_init_buf()),
|
|
|
|
* @iov is equal to &@local_iov, and @size is valid, as it has same
|
|
|
|
* offset and type as @local_iov.iov_len, which is guaranteed by
|
|
|
|
* static assertion below.
|
|
|
|
*
|
|
|
|
* @nalloc is always valid and is -1 both for embedded and external
|
|
|
|
* cases. It is included in the union only to ensure the padding prior
|
|
|
|
* to the @size field will not result in a 0-length array.
|
|
|
|
*/
|
|
|
|
union {
|
|
|
|
struct {
|
|
|
|
int nalloc;
|
|
|
|
struct iovec local_iov;
|
|
|
|
};
|
|
|
|
struct {
|
|
|
|
char __pad[sizeof(int) + offsetof(struct iovec, iov_len)];
|
|
|
|
size_t size;
|
|
|
|
};
|
|
|
|
};
|
2016-03-09 10:52:44 +01:00
|
|
|
} QEMUIOVector;
|
|
|
|
|
2019-02-18 15:09:10 +01:00
|
|
|
QEMU_BUILD_BUG_ON(offsetof(QEMUIOVector, size) !=
|
|
|
|
offsetof(QEMUIOVector, local_iov.iov_len));
|
|
|
|
|
|
|
|
#define QEMU_IOVEC_INIT_BUF(self, buf, len) \
|
|
|
|
{ \
|
|
|
|
.iov = &(self).local_iov, \
|
|
|
|
.niov = 1, \
|
|
|
|
.nalloc = -1, \
|
|
|
|
.local_iov = { \
|
|
|
|
.iov_base = (void *)(buf), /* cast away const */ \
|
|
|
|
.iov_len = (len), \
|
|
|
|
}, \
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* qemu_iovec_init_buf
|
|
|
|
*
|
|
|
|
* Initialize embedded QEMUIOVector.
|
|
|
|
*
|
|
|
|
* Note: "const" is used over @buf pointer to make it simple to pass
|
|
|
|
* const pointers, appearing in read functions. Then this "const" is
|
|
|
|
* cast away by QEMU_IOVEC_INIT_BUF().
|
|
|
|
*/
|
|
|
|
static inline void qemu_iovec_init_buf(QEMUIOVector *qiov,
|
|
|
|
const void *buf, size_t len)
|
|
|
|
{
|
|
|
|
*qiov = (QEMUIOVector) QEMU_IOVEC_INIT_BUF(*qiov, buf, len);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void *qemu_iovec_buf(QEMUIOVector *qiov)
|
|
|
|
{
|
|
|
|
/* Only supports embedded iov */
|
|
|
|
assert(qiov->nalloc == -1 && qiov->iov == &qiov->local_iov);
|
|
|
|
|
|
|
|
return qiov->local_iov.iov_base;
|
|
|
|
}
|
|
|
|
|
2016-03-09 10:52:44 +01:00
|
|
|
void qemu_iovec_init(QEMUIOVector *qiov, int alloc_hint);
|
|
|
|
void qemu_iovec_init_external(QEMUIOVector *qiov, struct iovec *iov, int niov);
|
2019-06-04 18:15:03 +02:00
|
|
|
void qemu_iovec_init_slice(QEMUIOVector *qiov, QEMUIOVector *source,
|
|
|
|
size_t offset, size_t len);
|
2023-04-11 19:34:15 +02:00
|
|
|
struct iovec *qemu_iovec_slice(QEMUIOVector *qiov,
|
|
|
|
size_t offset, size_t len,
|
|
|
|
size_t *head, size_t *tail, int *niov);
|
2019-06-04 18:15:14 +02:00
|
|
|
int qemu_iovec_subvec_niov(QEMUIOVector *qiov, size_t offset, size_t len);
|
2016-03-09 10:52:44 +01:00
|
|
|
void qemu_iovec_add(QEMUIOVector *qiov, void *base, size_t len);
|
|
|
|
void qemu_iovec_concat(QEMUIOVector *dst,
|
|
|
|
QEMUIOVector *src, size_t soffset, size_t sbytes);
|
|
|
|
size_t qemu_iovec_concat_iov(QEMUIOVector *dst,
|
|
|
|
struct iovec *src_iov, unsigned int src_cnt,
|
|
|
|
size_t soffset, size_t sbytes);
|
2019-06-04 18:15:04 +02:00
|
|
|
bool qemu_iovec_is_zero(QEMUIOVector *qiov, size_t qiov_offeset, size_t bytes);
|
2016-03-09 10:52:44 +01:00
|
|
|
void qemu_iovec_destroy(QEMUIOVector *qiov);
|
|
|
|
void qemu_iovec_reset(QEMUIOVector *qiov);
|
|
|
|
size_t qemu_iovec_to_buf(QEMUIOVector *qiov, size_t offset,
|
|
|
|
void *buf, size_t bytes);
|
|
|
|
size_t qemu_iovec_from_buf(QEMUIOVector *qiov, size_t offset,
|
|
|
|
const void *buf, size_t bytes);
|
|
|
|
size_t qemu_iovec_memset(QEMUIOVector *qiov, size_t offset,
|
|
|
|
int fillc, size_t bytes);
|
|
|
|
ssize_t qemu_iovec_compare(QEMUIOVector *a, QEMUIOVector *b);
|
|
|
|
void qemu_iovec_clone(QEMUIOVector *dest, const QEMUIOVector *src, void *buf);
|
|
|
|
void qemu_iovec_discard_back(QEMUIOVector *qiov, size_t bytes);
|
|
|
|
|
2012-12-06 12:15:58 +01:00
|
|
|
#endif
|