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,8 +35,7 @@ typedef struct VirtIOBlockReq | ||
| 35 | VirtQueueElement elem; | 35 | VirtQueueElement elem; |
| 36 | struct virtio_blk_inhdr *in; | 36 | struct virtio_blk_inhdr *in; |
| 37 | struct virtio_blk_outhdr *out; | 37 | struct virtio_blk_outhdr *out; |
| 38 | - size_t size; | ||
| 39 | - uint8_t *buffer; | 38 | + QEMUIOVector qiov; |
| 40 | struct VirtIOBlockReq *next; | 39 | struct VirtIOBlockReq *next; |
| 41 | } VirtIOBlockReq; | 40 | } VirtIOBlockReq; |
| 42 | 41 | ||
| @@ -45,10 +44,9 @@ static void virtio_blk_req_complete(VirtIOBlockReq *req, int status) | @@ -45,10 +44,9 @@ static void virtio_blk_req_complete(VirtIOBlockReq *req, int status) | ||
| 45 | VirtIOBlock *s = req->dev; | 44 | VirtIOBlock *s = req->dev; |
| 46 | 45 | ||
| 47 | req->in->status = status; | 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 | virtio_notify(&s->vdev, s->vq); | 48 | virtio_notify(&s->vdev, s->vq); |
| 50 | 49 | ||
| 51 | - qemu_free(req->buffer); | ||
| 52 | qemu_free(req); | 50 | qemu_free(req); |
| 53 | } | 51 | } |
| 54 | 52 | ||
| @@ -76,24 +74,7 @@ static void virtio_blk_rw_complete(void *opaque, int ret) | @@ -76,24 +74,7 @@ static void virtio_blk_rw_complete(void *opaque, int ret) | ||
| 76 | { | 74 | { |
| 77 | VirtIOBlockReq *req = opaque; | 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 | if (virtio_blk_handle_write_error(req, -ret)) | 78 | if (virtio_blk_handle_write_error(req, -ret)) |
| 98 | return; | 79 | return; |
| 99 | } | 80 | } |
| @@ -122,39 +103,16 @@ static VirtIOBlockReq *virtio_blk_get_request(VirtIOBlock *s) | @@ -122,39 +103,16 @@ static VirtIOBlockReq *virtio_blk_get_request(VirtIOBlock *s) | ||
| 122 | return req; | 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 | static void virtio_blk_handle_output(VirtIODevice *vdev, VirtQueue *vq) | 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,8 +121,6 @@ static void virtio_blk_handle_output(VirtIODevice *vdev, VirtQueue *vq) | ||
| 163 | VirtIOBlockReq *req; | 121 | VirtIOBlockReq *req; |
| 164 | 122 | ||
| 165 | while ((req = virtio_blk_get_request(s))) { | 123 | while ((req = virtio_blk_get_request(s))) { |
| 166 | - int i; | ||
| 167 | - | ||
| 168 | if (req->elem.out_num < 1 || req->elem.in_num < 1) { | 124 | if (req->elem.out_num < 1 || req->elem.in_num < 1) { |
| 169 | fprintf(stderr, "virtio-blk missing headers\n"); | 125 | fprintf(stderr, "virtio-blk missing headers\n"); |
| 170 | exit(1); | 126 | exit(1); |
| @@ -187,23 +143,13 @@ static void virtio_blk_handle_output(VirtIODevice *vdev, VirtQueue *vq) | @@ -187,23 +143,13 @@ static void virtio_blk_handle_output(VirtIODevice *vdev, VirtQueue *vq) | ||
| 187 | virtio_notify(vdev, vq); | 143 | virtio_notify(vdev, vq); |
| 188 | qemu_free(req); | 144 | qemu_free(req); |
| 189 | } else if (req->out->type & VIRTIO_BLK_T_OUT) { | 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 | } else { | 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 | /* |