diff --git a/hw/rtl8139.c b/hw/rtl8139.c index eb22d04fad829e89ffdd71d2bf6ec6b7f909e08f..8128b64a0fefbfd6b2b8438c5ffb9732bafd7e2e 100644 --- a/hw/rtl8139.c +++ b/hw/rtl8139.c @@ -1783,7 +1783,7 @@ static void rtl8139_transfer_frame(RTL8139State *s, uint8_t *buf, int size, if (iov) { buf2_size = iov_size(iov, 3); buf2 = g_malloc(buf2_size); - iov_to_buf(iov, 3, buf2, 0, buf2_size); + iov_to_buf(iov, 3, 0, buf2, buf2_size); buf = buf2; } diff --git a/hw/usb/core.c b/hw/usb/core.c index 0e02da760152672a23d7ac0e371545bbdfd04fd0..2641685a3228ee7e431dfaa7b71486086359df17 100644 --- a/hw/usb/core.c +++ b/hw/usb/core.c @@ -522,10 +522,10 @@ void usb_packet_copy(USBPacket *p, void *ptr, size_t bytes) switch (p->pid) { case USB_TOKEN_SETUP: case USB_TOKEN_OUT: - iov_to_buf(p->iov.iov, p->iov.niov, ptr, p->result, bytes); + iov_to_buf(p->iov.iov, p->iov.niov, p->result, ptr, bytes); break; case USB_TOKEN_IN: - iov_from_buf(p->iov.iov, p->iov.niov, ptr, p->result, bytes); + iov_from_buf(p->iov.iov, p->iov.niov, p->result, ptr, bytes); break; default: fprintf(stderr, "%s: invalid pid: %x\n", __func__, p->pid); @@ -539,7 +539,7 @@ void usb_packet_skip(USBPacket *p, size_t bytes) assert(p->result >= 0); assert(p->result + bytes <= p->iov.size); if (p->pid == USB_TOKEN_IN) { - iov_clear(p->iov.iov, p->iov.niov, p->result, bytes); + iov_memset(p->iov.iov, p->iov.niov, p->result, 0, bytes); } p->result += bytes; } diff --git a/hw/virtio-balloon.c b/hw/virtio-balloon.c index 075ed87e3745ef0dcb4d62abaf195154042cedc7..23effa40a08b4e829e163ee68aafca9431404b6e 100644 --- a/hw/virtio-balloon.c +++ b/hw/virtio-balloon.c @@ -77,7 +77,7 @@ static void virtio_balloon_handle_output(VirtIODevice *vdev, VirtQueue *vq) size_t offset = 0; uint32_t pfn; - while (iov_to_buf(elem.out_sg, elem.out_num, &pfn, offset, 4) == 4) { + while (iov_to_buf(elem.out_sg, elem.out_num, offset, &pfn, 4) == 4) { ram_addr_t pa; ram_addr_t addr; @@ -118,7 +118,7 @@ static void virtio_balloon_receive_stats(VirtIODevice *vdev, VirtQueue *vq) */ reset_stats(s); - while (iov_to_buf(elem->out_sg, elem->out_num, &stat, offset, sizeof(stat)) + while (iov_to_buf(elem->out_sg, elem->out_num, offset, &stat, sizeof(stat)) == sizeof(stat)) { uint16_t tag = tswap16(stat.tag); uint64_t val = tswap64(stat.val); diff --git a/hw/virtio-net.c b/hw/virtio-net.c index 3f190d417efdd9ee8cd56eb026ae2bf817d32e2b..533aa3d0f321fa04e79381e5c4a1388ea6b671aa 100644 --- a/hw/virtio-net.c +++ b/hw/virtio-net.c @@ -656,8 +656,8 @@ static ssize_t virtio_net_receive(VLANClientState *nc, const uint8_t *buf, size_ } /* copy in packet. ugh */ - len = iov_from_buf(sg, elem.in_num, - buf + offset, 0, size - offset); + len = iov_from_buf(sg, elem.in_num, 0, + buf + offset, size - offset); total += len; offset += len; /* If buffers can't be merged, at this point we diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c index 1e477e5a33bab85770b377a404ab7c93a5d4eb03..728f218dcf29c016e3ce4169c55dc3b8960dcea1 100644 --- a/hw/virtio-serial-bus.c +++ b/hw/virtio-serial-bus.c @@ -106,8 +106,8 @@ static size_t write_to_port(VirtIOSerialPort *port, break; } - len = iov_from_buf(elem.in_sg, elem.in_num, - buf + offset, 0, size - offset); + len = iov_from_buf(elem.in_sg, elem.in_num, 0, + buf + offset, size - offset); offset += len; virtqueue_push(vq, &elem, len); @@ -467,7 +467,7 @@ static void control_out(VirtIODevice *vdev, VirtQueue *vq) buf = g_malloc(cur_len); len = cur_len; } - iov_to_buf(elem.out_sg, elem.out_num, buf, 0, cur_len); + iov_to_buf(elem.out_sg, elem.out_num, 0, buf, cur_len); handle_control_message(vser, buf, cur_len); virtqueue_push(vq, &elem, 0); diff --git a/iov.c b/iov.c index 0f964939d0e9ecd7e4b64a87fac72511be91ca47..bc58cab05a833b905bc38770109768f2b20ea66c 100644 --- a/iov.c +++ b/iov.c @@ -17,8 +17,8 @@ #include "iov.h" -size_t iov_from_buf(struct iovec *iov, unsigned int iov_cnt, - const void *buf, size_t iov_off, size_t size) +size_t iov_from_buf(struct iovec *iov, unsigned int iov_cnt, size_t iov_off, + const void *buf, size_t size) { size_t iovec_off, buf_off; unsigned int i; @@ -40,8 +40,8 @@ size_t iov_from_buf(struct iovec *iov, unsigned int iov_cnt, return buf_off; } -size_t iov_to_buf(const struct iovec *iov, const unsigned int iov_cnt, - void *buf, size_t iov_off, size_t size) +size_t iov_to_buf(const struct iovec *iov, const unsigned int iov_cnt, size_t iov_off, + void *buf, size_t size) { uint8_t *ptr; size_t iovec_off, buf_off; @@ -65,8 +65,8 @@ size_t iov_to_buf(const struct iovec *iov, const unsigned int iov_cnt, return buf_off; } -size_t iov_clear(const struct iovec *iov, const unsigned int iov_cnt, - size_t iov_off, size_t size) +size_t iov_memset(const struct iovec *iov, const unsigned int iov_cnt, + size_t iov_off, int fillc, size_t size) { size_t iovec_off, buf_off; unsigned int i; @@ -77,7 +77,7 @@ size_t iov_clear(const struct iovec *iov, const unsigned int iov_cnt, if (iov_off < (iovec_off + iov[i].iov_len)) { size_t len = MIN((iovec_off + iov[i].iov_len) - iov_off , size); - memset(iov[i].iov_base + (iov_off - iovec_off), 0, len); + memset(iov[i].iov_base + (iov_off - iovec_off), fillc, len); buf_off += len; iov_off += len; diff --git a/iov.h b/iov.h index 94d2f7828433890d133d37fff8d2b1122450d267..0b4acf4a513a0ae9b5cce72a9432238f472ffb8c 100644 --- a/iov.h +++ b/iov.h @@ -12,12 +12,44 @@ #include "qemu-common.h" +/** + * 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) + */ size_t iov_from_buf(struct iovec *iov, unsigned int iov_cnt, - const void *buf, size_t iov_off, size_t size); + size_t offset, const void *buf, size_t bytes); size_t iov_to_buf(const struct iovec *iov, const unsigned int iov_cnt, - void *buf, size_t iov_off, size_t size); -size_t iov_size(const struct iovec *iov, const unsigned int iov_cnt); -size_t iov_clear(const struct iovec *iov, const unsigned int iov_cnt, - size_t iov_off, size_t size); + size_t offset, void *buf, size_t bytes); + +/** + * Set data bytes pointed out by iovec `iov' of size `iov_cnt' elements, + * starting at byte offset `start', to value `fillc', repeating it + * `bytes' number of times. + * 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); + +/** + * 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. + */ void iov_hexdump(const struct iovec *iov, const unsigned int iov_cnt, FILE *fp, const char *prefix, size_t limit); diff --git a/net.c b/net.c index 4aa416cffb743cee3660e5a318d52693232f7bf0..abf0fd0a0d38cdeb9a27b472e0117ad931dff0b6 100644 --- a/net.c +++ b/net.c @@ -544,7 +544,7 @@ static ssize_t vc_sendv_compat(VLANClientState *vc, const struct iovec *iov, uint8_t buffer[4096]; size_t offset; - offset = iov_to_buf(iov, iovcnt, buffer, 0, sizeof(buffer)); + offset = iov_to_buf(iov, iovcnt, 0, buffer, sizeof(buffer)); return vc->info->receive(vc, buffer, offset); }