Commit d28a1b6ec6e6d7d03ed72852ea04190feb2a7638

Authored by aliguori
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 /*
... ...