Right now, virtio-net modifies the iovec structure in VirtQueueElement. This is
evil. This creates an impossible situation if we want to bounce iovec buffers
in VirtQueueElement as we lose track of the original buffers and the resulting
free results in very bad things.
I tried to refactor receive_headers() and iov_fill() to be able to skip the
header if present but failed miserably. Instead of spending more time trying to
get that to work, I simply decided to leave the code as-is and copy the iovec
to a temporary buffer.
I doubt there will be any performance impact as usually there are only a few
elements in the iovec anyway.
Signed-off-by: Anthony Liguori <[EMAIL PROTECTED]>
diff --git a/qemu/hw/virtio-net.c b/qemu/hw/virtio-net.c
index b64fb00..6493ff6 100644
--- a/qemu/hw/virtio-net.c
+++ b/qemu/hw/virtio-net.c
@@ -198,6 +198,7 @@ static void virtio_net_receive(void *opaque, const uint8_t
*buf, int size)
while (offset < size) {
VirtQueueElement elem;
int len, total;
+ struct iovec sg[VIRTQUEUE_MAX_SIZE];
len = total = 0;
@@ -219,17 +220,19 @@ static void virtio_net_receive(void *opaque, const
uint8_t *buf, int size)
exit(1);
}
+ memcpy(&sg, &elem.in_sg[0], sizeof(sg[0]) * elem.in_num);
+
if (i == 0) {
if (n->mergeable_rx_bufs)
- mhdr = (struct virtio_net_hdr_mrg_rxbuf
*)elem.in_sg[0].iov_base;
+ mhdr = (struct virtio_net_hdr_mrg_rxbuf *)sg[0].iov_base;
- offset += receive_header(n, &elem.in_sg[0], elem.in_num,
+ offset += receive_header(n, sg, elem.in_num,
buf + offset, size - offset, hdr_len);
total += hdr_len;
}
/* copy in packet. ugh */
- len = iov_fill(&elem.in_sg[0], elem.in_num,
+ len = iov_fill(sg, elem.in_num,
buf + offset, size - offset);
total += len;
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at http://vger.kernel.org/majordomo-info.html