Commit d28a1b6ec6e6d7d03ed72852ea04190feb2a7638
1 parent
522584a5
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
Showing
1 changed file
with
17 additions
and
71 deletions
hw/virtio-blk.c
| ... | ... | @@ -35,8 +35,7 @@ typedef struct VirtIOBlockReq |
| 35 | 35 | VirtQueueElement elem; |
| 36 | 36 | struct virtio_blk_inhdr *in; |
| 37 | 37 | struct virtio_blk_outhdr *out; |
| 38 | - size_t size; | |
| 39 | - uint8_t *buffer; | |
| 38 | + QEMUIOVector qiov; | |
| 40 | 39 | struct VirtIOBlockReq *next; |
| 41 | 40 | } VirtIOBlockReq; |
| 42 | 41 | |
| ... | ... | @@ -45,10 +44,9 @@ static void virtio_blk_req_complete(VirtIOBlockReq *req, int status) |
| 45 | 44 | VirtIOBlock *s = req->dev; |
| 46 | 45 | |
| 47 | 46 | req->in->status = status; |
| 48 | - virtqueue_push(s->vq, &req->elem, req->size + sizeof(*req->in)); | |
| 47 | + virtqueue_push(s->vq, &req->elem, req->qiov.size + sizeof(*req->in)); | |
| 49 | 48 | virtio_notify(&s->vdev, s->vq); |
| 50 | 49 | |
| 51 | - qemu_free(req->buffer); | |
| 52 | 50 | qemu_free(req); |
| 53 | 51 | } |
| 54 | 52 | |
| ... | ... | @@ -76,24 +74,7 @@ static void virtio_blk_rw_complete(void *opaque, int ret) |
| 76 | 74 | { |
| 77 | 75 | VirtIOBlockReq *req = opaque; |
| 78 | 76 | |
| 79 | - /* Copy read data to the guest */ | |
| 80 | - if (!ret && !(req->out->type & VIRTIO_BLK_T_OUT)) { | |
| 81 | - size_t offset = 0; | |
| 82 | - int i; | |
| 83 | - | |
| 84 | - for (i = 0; i < req->elem.in_num - 1; i++) { | |
| 85 | - size_t len; | |
| 86 | - | |
| 87 | - /* Be pretty defensive wrt malicious guests */ | |
| 88 | - len = MIN(req->elem.in_sg[i].iov_len, | |
| 89 | - req->size - offset); | |
| 90 | - | |
| 91 | - memcpy(req->elem.in_sg[i].iov_base, | |
| 92 | - req->buffer + offset, | |
| 93 | - len); | |
| 94 | - offset += len; | |
| 95 | - } | |
| 96 | - } else if (ret && (req->out->type & VIRTIO_BLK_T_OUT)) { | |
| 77 | + if (ret && (req->out->type & VIRTIO_BLK_T_OUT)) { | |
| 97 | 78 | if (virtio_blk_handle_write_error(req, -ret)) |
| 98 | 79 | return; |
| 99 | 80 | } |
| ... | ... | @@ -122,39 +103,16 @@ static VirtIOBlockReq *virtio_blk_get_request(VirtIOBlock *s) |
| 122 | 103 | return req; |
| 123 | 104 | } |
| 124 | 105 | |
| 125 | -static int virtio_blk_handle_write(VirtIOBlockReq *req) | |
| 106 | +static void virtio_blk_handle_write(VirtIOBlockReq *req) | |
| 126 | 107 | { |
| 127 | - if (!req->buffer) { | |
| 128 | - size_t offset = 0; | |
| 129 | - int i; | |
| 130 | - | |
| 131 | - for (i = 1; i < req->elem.out_num; i++) | |
| 132 | - req->size += req->elem.out_sg[i].iov_len; | |
| 133 | - | |
| 134 | - req->buffer = qemu_memalign(512, req->size); | |
| 135 | - if (req->buffer == NULL) { | |
| 136 | - qemu_free(req); | |
| 137 | - return -1; | |
| 138 | - } | |
| 139 | - | |
| 140 | - /* We copy the data from the SG list to avoid splitting up the request. | |
| 141 | - This helps performance a lot until we can pass full sg lists as AIO | |
| 142 | - operations */ | |
| 143 | - for (i = 1; i < req->elem.out_num; i++) { | |
| 144 | - size_t len; | |
| 145 | - | |
| 146 | - len = MIN(req->elem.out_sg[i].iov_len, | |
| 147 | - req->size - offset); | |
| 148 | - memcpy(req->buffer + offset, | |
| 149 | - req->elem.out_sg[i].iov_base, | |
| 150 | - len); | |
| 151 | - offset += len; | |
| 152 | - } | |
| 153 | - } | |
| 108 | + bdrv_aio_writev(req->dev->bs, req->out->sector, &req->qiov, | |
| 109 | + req->qiov.size / 512, virtio_blk_rw_complete, req); | |
| 110 | +} | |
| 154 | 111 | |
| 155 | - bdrv_aio_write(req->dev->bs, req->out->sector, req->buffer, req->size / 512, | |
| 156 | - virtio_blk_rw_complete, req); | |
| 157 | - return 0; | |
| 112 | +static void virtio_blk_handle_read(VirtIOBlockReq *req) | |
| 113 | +{ | |
| 114 | + bdrv_aio_readv(req->dev->bs, req->out->sector, &req->qiov, | |
| 115 | + req->qiov.size / 512, virtio_blk_rw_complete, req); | |
| 158 | 116 | } |
| 159 | 117 | |
| 160 | 118 | static void virtio_blk_handle_output(VirtIODevice *vdev, VirtQueue *vq) |
| ... | ... | @@ -163,8 +121,6 @@ static void virtio_blk_handle_output(VirtIODevice *vdev, VirtQueue *vq) |
| 163 | 121 | VirtIOBlockReq *req; |
| 164 | 122 | |
| 165 | 123 | while ((req = virtio_blk_get_request(s))) { |
| 166 | - int i; | |
| 167 | - | |
| 168 | 124 | if (req->elem.out_num < 1 || req->elem.in_num < 1) { |
| 169 | 125 | fprintf(stderr, "virtio-blk missing headers\n"); |
| 170 | 126 | exit(1); |
| ... | ... | @@ -187,23 +143,13 @@ static void virtio_blk_handle_output(VirtIODevice *vdev, VirtQueue *vq) |
| 187 | 143 | virtio_notify(vdev, vq); |
| 188 | 144 | qemu_free(req); |
| 189 | 145 | } else if (req->out->type & VIRTIO_BLK_T_OUT) { |
| 190 | - if (virtio_blk_handle_write(req) < 0) | |
| 191 | - break; | |
| 146 | + qemu_iovec_init_external(&req->qiov, &req->elem.out_sg[1], | |
| 147 | + req->elem.out_num - 1); | |
| 148 | + virtio_blk_handle_write(req); | |
| 192 | 149 | } else { |
| 193 | - for (i = 0; i < req->elem.in_num - 1; i++) | |
| 194 | - req->size += req->elem.in_sg[i].iov_len; | |
| 195 | - | |
| 196 | - req->buffer = qemu_memalign(512, req->size); | |
| 197 | - if (req->buffer == NULL) { | |
| 198 | - qemu_free(req); | |
| 199 | - break; | |
| 200 | - } | |
| 201 | - | |
| 202 | - bdrv_aio_read(s->bs, req->out->sector, | |
| 203 | - req->buffer, | |
| 204 | - req->size / 512, | |
| 205 | - virtio_blk_rw_complete, | |
| 206 | - req); | |
| 150 | + qemu_iovec_init_external(&req->qiov, &req->elem.in_sg[0], | |
| 151 | + req->elem.in_num - 1); | |
| 152 | + virtio_blk_handle_read(req); | |
| 207 | 153 | } |
| 208 | 154 | } |
| 209 | 155 | /* | ... | ... |