iov: reorganize iov_send_recv, part 2
Do not touch the "bytes" argument anymore. Instead, remember the original length of the last iovec if we touch it, and restore it afterwards. This requires undoing the changes in opposite order. The previous algorithm didn't care. Reviewed-by: Juan Quintela <quintela@redhat.com> Reviewed-by: Orit Wassermann <owasserm@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
cb6247a7e3
commit
5209d6753c
28
util/iov.c
28
util/iov.c
@ -145,7 +145,9 @@ ssize_t iov_send_recv(int sockfd, struct iovec *iov, unsigned iov_cnt,
|
|||||||
bool do_send)
|
bool do_send)
|
||||||
{
|
{
|
||||||
ssize_t ret;
|
ssize_t ret;
|
||||||
|
size_t orig_len, tail;
|
||||||
unsigned si, ei; /* start and end indexes */
|
unsigned si, ei; /* start and end indexes */
|
||||||
|
|
||||||
if (bytes == 0) {
|
if (bytes == 0) {
|
||||||
/* Catch the do-nothing case early, as otherwise we will pass an
|
/* Catch the do-nothing case early, as otherwise we will pass an
|
||||||
* empty iovec to sendmsg/recvmsg(), and not all implementations
|
* empty iovec to sendmsg/recvmsg(), and not all implementations
|
||||||
@ -174,31 +176,29 @@ ssize_t iov_send_recv(int sockfd, struct iovec *iov, unsigned iov_cnt,
|
|||||||
}
|
}
|
||||||
/* Find the end position skipping `bytes' bytes: */
|
/* Find the end position skipping `bytes' bytes: */
|
||||||
/* first, skip all full-sized elements */
|
/* first, skip all full-sized elements */
|
||||||
for (ei = 0; ei < iov_cnt && iov[ei].iov_len <= bytes; ++ei) {
|
tail = bytes;
|
||||||
bytes -= iov[ei].iov_len;
|
for (ei = 0; ei < iov_cnt && iov[ei].iov_len <= tail; ++ei) {
|
||||||
|
tail -= iov[ei].iov_len;
|
||||||
}
|
}
|
||||||
if (bytes) {
|
if (tail) {
|
||||||
/* second, fixup the last element, and remember
|
/* second, fixup the last element, and remember the original
|
||||||
* the length we've cut from the end of it in `bytes' */
|
* length */
|
||||||
size_t tail;
|
|
||||||
assert(ei < iov_cnt);
|
assert(ei < iov_cnt);
|
||||||
assert(iov[ei].iov_len > bytes);
|
assert(iov[ei].iov_len > tail);
|
||||||
tail = iov[ei].iov_len - bytes;
|
orig_len = iov[ei].iov_len;
|
||||||
iov[ei].iov_len = bytes;
|
iov[ei++].iov_len = tail;
|
||||||
bytes = tail; /* bytes is now equal to the tail size */
|
|
||||||
++ei;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = do_send_recv(sockfd, iov, ei, do_send);
|
ret = do_send_recv(sockfd, iov, ei, do_send);
|
||||||
|
|
||||||
/* Undo the changes above */
|
/* Undo the changes above */
|
||||||
|
if (tail) {
|
||||||
|
iov[ei-1].iov_len = orig_len;
|
||||||
|
}
|
||||||
if (offset) {
|
if (offset) {
|
||||||
iov[0].iov_base -= offset;
|
iov[0].iov_base -= offset;
|
||||||
iov[0].iov_len += offset;
|
iov[0].iov_len += offset;
|
||||||
}
|
}
|
||||||
if (bytes) {
|
|
||||||
iov[ei-1].iov_len += bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user