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 | /* | ... | ... |