On Fri, 15 Jan 2016 13:41:53 +0100 Paolo Bonzini <[email protected]> wrote:
> Build the addresses and s/g lists on the stack, and then copy them > to a VirtQueueElement that is just as big as required to contain this > particular s/g list. The cost of the copy is minimal compared to that > of a large malloc. > > When virtqueue_map is used on the destination side of migration or on > loadvm, the iovecs have already been split at memory region boundary, > so we can just reuse the out_num/in_num we find in the file. > > Signed-off-by: Paolo Bonzini <[email protected]> > --- > hw/virtio/virtio.c | 82 > +++++++++++++++++++++++++++++++++--------------------- > 1 file changed, 51 insertions(+), 31 deletions(-) > > /* Collect all the descriptors */ > do { > - struct iovec *sg; > + hwaddr pa = vring_desc_addr(vdev, desc_pa, i); > + size_t len = vring_desc_len(vdev, desc_pa, i); > > if (vring_desc_flags(vdev, desc_pa, i) & VRING_DESC_F_WRITE) { > - if (elem->in_num >= VIRTQUEUE_MAX_SIZE) { > - error_report("Too many write descriptors in indirect table"); > - exit(1); > - } > - elem->in_addr[elem->in_num] = vring_desc_addr(vdev, desc_pa, i); > - sg = &elem->in_sg[elem->in_num++]; > + virtqueue_map_desc(&in_num, addr + out_num, iov + out_num, > + VIRTQUEUE_MAX_SIZE - out_num, 1, pa, len); Minor nit: I'd probably use 'true' here... > } else { > - if (elem->out_num >= VIRTQUEUE_MAX_SIZE) { > - error_report("Too many read descriptors in indirect table"); > + if (in_num) { > + error_report("Incorrect order for descriptors"); > exit(1); > } > - elem->out_addr[elem->out_num] = vring_desc_addr(vdev, desc_pa, > i); > - sg = &elem->out_sg[elem->out_num++]; > + virtqueue_map_desc(&out_num, addr, iov, > + VIRTQUEUE_MAX_SIZE, 0, pa, len); ...and 'false' here. > } > > - sg->iov_len = vring_desc_len(vdev, desc_pa, i); > - > /* If we've got too many, that implies a descriptor loop. */ > - if ((elem->in_num + elem->out_num) > max) { > + if ((in_num + out_num) > max) { > error_report("Looped descriptor"); > exit(1); > } > } while ((i = virtqueue_next_desc(vdev, desc_pa, i, max)) != max); Reviewed-by: Cornelia Huck <[email protected]>
