Revision 91553dcc hw/virtio-blk.c
b/hw/virtio-blk.c | ||
---|---|---|
252 | 252 |
} |
253 | 253 |
#endif /* __linux__ */ |
254 | 254 |
|
255 |
static void virtio_blk_handle_write(VirtIOBlockReq *req) |
|
255 |
static void do_multiwrite(BlockDriverState *bs, BlockRequest *blkreq, |
|
256 |
int num_writes) |
|
256 | 257 |
{ |
257 |
BlockDriverAIOCB *acb; |
|
258 |
int i, ret; |
|
259 |
ret = bdrv_aio_multiwrite(bs, blkreq, num_writes); |
|
260 |
|
|
261 |
if (ret != 0) { |
|
262 |
for (i = 0; i < num_writes; i++) { |
|
263 |
if (blkreq[i].error) { |
|
264 |
virtio_blk_req_complete(blkreq[i].opaque, VIRTIO_BLK_S_IOERR); |
|
265 |
} |
|
266 |
} |
|
267 |
} |
|
268 |
} |
|
258 | 269 |
|
259 |
acb = bdrv_aio_writev(req->dev->bs, req->out->sector, &req->qiov, |
|
260 |
req->qiov.size / 512, virtio_blk_rw_complete, req); |
|
261 |
if (!acb) { |
|
262 |
virtio_blk_req_complete(req, VIRTIO_BLK_S_IOERR); |
|
270 |
static void virtio_blk_handle_write(BlockRequest *blkreq, int *num_writes, |
|
271 |
VirtIOBlockReq *req, BlockDriverState **old_bs) |
|
272 |
{ |
|
273 |
if (req->dev->bs != *old_bs || *num_writes == 32) { |
|
274 |
if (*old_bs != NULL) { |
|
275 |
do_multiwrite(*old_bs, blkreq, *num_writes); |
|
276 |
} |
|
277 |
*num_writes = 0; |
|
278 |
*old_bs = req->dev->bs; |
|
263 | 279 |
} |
280 |
|
|
281 |
blkreq[*num_writes].sector = req->out->sector; |
|
282 |
blkreq[*num_writes].nb_sectors = req->qiov.size / 512; |
|
283 |
blkreq[*num_writes].qiov = &req->qiov; |
|
284 |
blkreq[*num_writes].cb = virtio_blk_rw_complete; |
|
285 |
blkreq[*num_writes].opaque = req; |
|
286 |
blkreq[*num_writes].error = 0; |
|
287 |
|
|
288 |
(*num_writes)++; |
|
264 | 289 |
} |
265 | 290 |
|
266 | 291 |
static void virtio_blk_handle_read(VirtIOBlockReq *req) |
... | ... | |
278 | 303 |
{ |
279 | 304 |
VirtIOBlock *s = to_virtio_blk(vdev); |
280 | 305 |
VirtIOBlockReq *req; |
306 |
BlockRequest blkreq[32]; |
|
307 |
int num_writes = 0; |
|
308 |
BlockDriverState *old_bs = NULL; |
|
281 | 309 |
|
282 | 310 |
while ((req = virtio_blk_get_request(s))) { |
283 | 311 |
if (req->elem.out_num < 1 || req->elem.in_num < 1) { |
... | ... | |
299 | 327 |
} else if (req->out->type & VIRTIO_BLK_T_OUT) { |
300 | 328 |
qemu_iovec_init_external(&req->qiov, &req->elem.out_sg[1], |
301 | 329 |
req->elem.out_num - 1); |
302 |
virtio_blk_handle_write(req);
|
|
330 |
virtio_blk_handle_write(blkreq, &num_writes, req, &old_bs);
|
|
303 | 331 |
} else { |
304 | 332 |
qemu_iovec_init_external(&req->qiov, &req->elem.in_sg[0], |
305 | 333 |
req->elem.in_num - 1); |
306 | 334 |
virtio_blk_handle_read(req); |
307 | 335 |
} |
308 | 336 |
} |
337 |
|
|
338 |
if (num_writes > 0) { |
|
339 |
do_multiwrite(old_bs, blkreq, num_writes); |
|
340 |
} |
|
341 |
|
|
309 | 342 |
/* |
310 | 343 |
* FIXME: Want to check for completions before returning to guest mode, |
311 | 344 |
* so cached reads and writes are reported as quickly as possible. But |
... | ... | |
324 | 357 |
s->rq = NULL; |
325 | 358 |
|
326 | 359 |
while (req) { |
327 |
virtio_blk_handle_write(req); |
|
360 |
bdrv_aio_writev(req->dev->bs, req->out->sector, &req->qiov, |
|
361 |
req->qiov.size / 512, virtio_blk_rw_complete, req); |
|
328 | 362 |
req = req->next; |
329 | 363 |
} |
330 | 364 |
} |
Also available in: Unified diff