mirror of https://gitee.com/openkylin/qemu.git
virtio-blk: use generic vectored I/O APIs (Christoph Hellwig)
Use the generic bdrv_aio_readv/bdrv_aio_writev APIs instead of linearizing buffers directly. This enables using the future native preadv/pwritev support. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6903 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
522584a57b
commit
d28a1b6ec6
|
@ -35,8 +35,7 @@ typedef struct VirtIOBlockReq
|
|||
VirtQueueElement elem;
|
||||
struct virtio_blk_inhdr *in;
|
||||
struct virtio_blk_outhdr *out;
|
||||
size_t size;
|
||||
uint8_t *buffer;
|
||||
QEMUIOVector qiov;
|
||||
struct VirtIOBlockReq *next;
|
||||
} VirtIOBlockReq;
|
||||
|
||||
|
@ -45,10 +44,9 @@ static void virtio_blk_req_complete(VirtIOBlockReq *req, int status)
|
|||
VirtIOBlock *s = req->dev;
|
||||
|
||||
req->in->status = status;
|
||||
virtqueue_push(s->vq, &req->elem, req->size + sizeof(*req->in));
|
||||
virtqueue_push(s->vq, &req->elem, req->qiov.size + sizeof(*req->in));
|
||||
virtio_notify(&s->vdev, s->vq);
|
||||
|
||||
qemu_free(req->buffer);
|
||||
qemu_free(req);
|
||||
}
|
||||
|
||||
|
@ -76,24 +74,7 @@ static void virtio_blk_rw_complete(void *opaque, int ret)
|
|||
{
|
||||
VirtIOBlockReq *req = opaque;
|
||||
|
||||
/* Copy read data to the guest */
|
||||
if (!ret && !(req->out->type & VIRTIO_BLK_T_OUT)) {
|
||||
size_t offset = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < req->elem.in_num - 1; i++) {
|
||||
size_t len;
|
||||
|
||||
/* Be pretty defensive wrt malicious guests */
|
||||
len = MIN(req->elem.in_sg[i].iov_len,
|
||||
req->size - offset);
|
||||
|
||||
memcpy(req->elem.in_sg[i].iov_base,
|
||||
req->buffer + offset,
|
||||
len);
|
||||
offset += len;
|
||||
}
|
||||
} else if (ret && (req->out->type & VIRTIO_BLK_T_OUT)) {
|
||||
if (ret && (req->out->type & VIRTIO_BLK_T_OUT)) {
|
||||
if (virtio_blk_handle_write_error(req, -ret))
|
||||
return;
|
||||
}
|
||||
|
@ -122,39 +103,16 @@ static VirtIOBlockReq *virtio_blk_get_request(VirtIOBlock *s)
|
|||
return req;
|
||||
}
|
||||
|
||||
static int virtio_blk_handle_write(VirtIOBlockReq *req)
|
||||
static void virtio_blk_handle_write(VirtIOBlockReq *req)
|
||||
{
|
||||
if (!req->buffer) {
|
||||
size_t offset = 0;
|
||||
int i;
|
||||
bdrv_aio_writev(req->dev->bs, req->out->sector, &req->qiov,
|
||||
req->qiov.size / 512, virtio_blk_rw_complete, req);
|
||||
}
|
||||
|
||||
for (i = 1; i < req->elem.out_num; i++)
|
||||
req->size += req->elem.out_sg[i].iov_len;
|
||||
|
||||
req->buffer = qemu_memalign(512, req->size);
|
||||
if (req->buffer == NULL) {
|
||||
qemu_free(req);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* We copy the data from the SG list to avoid splitting up the request.
|
||||
This helps performance a lot until we can pass full sg lists as AIO
|
||||
operations */
|
||||
for (i = 1; i < req->elem.out_num; i++) {
|
||||
size_t len;
|
||||
|
||||
len = MIN(req->elem.out_sg[i].iov_len,
|
||||
req->size - offset);
|
||||
memcpy(req->buffer + offset,
|
||||
req->elem.out_sg[i].iov_base,
|
||||
len);
|
||||
offset += len;
|
||||
}
|
||||
}
|
||||
|
||||
bdrv_aio_write(req->dev->bs, req->out->sector, req->buffer, req->size / 512,
|
||||
virtio_blk_rw_complete, req);
|
||||
return 0;
|
||||
static void virtio_blk_handle_read(VirtIOBlockReq *req)
|
||||
{
|
||||
bdrv_aio_readv(req->dev->bs, req->out->sector, &req->qiov,
|
||||
req->qiov.size / 512, virtio_blk_rw_complete, req);
|
||||
}
|
||||
|
||||
static void virtio_blk_handle_output(VirtIODevice *vdev, VirtQueue *vq)
|
||||
|
@ -163,8 +121,6 @@ static void virtio_blk_handle_output(VirtIODevice *vdev, VirtQueue *vq)
|
|||
VirtIOBlockReq *req;
|
||||
|
||||
while ((req = virtio_blk_get_request(s))) {
|
||||
int i;
|
||||
|
||||
if (req->elem.out_num < 1 || req->elem.in_num < 1) {
|
||||
fprintf(stderr, "virtio-blk missing headers\n");
|
||||
exit(1);
|
||||
|
@ -187,23 +143,13 @@ static void virtio_blk_handle_output(VirtIODevice *vdev, VirtQueue *vq)
|
|||
virtio_notify(vdev, vq);
|
||||
qemu_free(req);
|
||||
} else if (req->out->type & VIRTIO_BLK_T_OUT) {
|
||||
if (virtio_blk_handle_write(req) < 0)
|
||||
break;
|
||||
qemu_iovec_init_external(&req->qiov, &req->elem.out_sg[1],
|
||||
req->elem.out_num - 1);
|
||||
virtio_blk_handle_write(req);
|
||||
} else {
|
||||
for (i = 0; i < req->elem.in_num - 1; i++)
|
||||
req->size += req->elem.in_sg[i].iov_len;
|
||||
|
||||
req->buffer = qemu_memalign(512, req->size);
|
||||
if (req->buffer == NULL) {
|
||||
qemu_free(req);
|
||||
break;
|
||||
}
|
||||
|
||||
bdrv_aio_read(s->bs, req->out->sector,
|
||||
req->buffer,
|
||||
req->size / 512,
|
||||
virtio_blk_rw_complete,
|
||||
req);
|
||||
qemu_iovec_init_external(&req->qiov, &req->elem.in_sg[0],
|
||||
req->elem.in_num - 1);
|
||||
virtio_blk_handle_read(req);
|
||||
}
|
||||
}
|
||||
/*
|
||||
|
|
Loading…
Reference in New Issue