Revision bc6694d4 hw/virtio-blk.c
b/hw/virtio-blk.c | ||
---|---|---|
317 | 317 |
} |
318 | 318 |
} |
319 | 319 |
|
320 |
typedef struct MultiReqBuffer { |
|
321 |
BlockRequest blkreq[32]; |
|
322 |
int num_writes; |
|
323 |
BlockDriverState *old_bs; |
|
324 |
} MultiReqBuffer; |
|
325 |
|
|
326 |
static void virtio_blk_handle_request(VirtIOBlockReq *req, |
|
327 |
MultiReqBuffer *mrb) |
|
328 |
{ |
|
329 |
if (req->elem.out_num < 1 || req->elem.in_num < 1) { |
|
330 |
fprintf(stderr, "virtio-blk missing headers\n"); |
|
331 |
exit(1); |
|
332 |
} |
|
333 |
|
|
334 |
if (req->elem.out_sg[0].iov_len < sizeof(*req->out) || |
|
335 |
req->elem.in_sg[req->elem.in_num - 1].iov_len < sizeof(*req->in)) { |
|
336 |
fprintf(stderr, "virtio-blk header not in correct element\n"); |
|
337 |
exit(1); |
|
338 |
} |
|
339 |
|
|
340 |
req->out = (void *)req->elem.out_sg[0].iov_base; |
|
341 |
req->in = (void *)req->elem.in_sg[req->elem.in_num - 1].iov_base; |
|
342 |
|
|
343 |
if (req->out->type & VIRTIO_BLK_T_FLUSH) { |
|
344 |
virtio_blk_handle_flush(req); |
|
345 |
} else if (req->out->type & VIRTIO_BLK_T_SCSI_CMD) { |
|
346 |
virtio_blk_handle_scsi(req); |
|
347 |
} else if (req->out->type & VIRTIO_BLK_T_OUT) { |
|
348 |
qemu_iovec_init_external(&req->qiov, &req->elem.out_sg[1], |
|
349 |
req->elem.out_num - 1); |
|
350 |
virtio_blk_handle_write(mrb->blkreq, &mrb->num_writes, |
|
351 |
req, &mrb->old_bs); |
|
352 |
} else { |
|
353 |
qemu_iovec_init_external(&req->qiov, &req->elem.in_sg[0], |
|
354 |
req->elem.in_num - 1); |
|
355 |
virtio_blk_handle_read(req); |
|
356 |
} |
|
357 |
} |
|
358 |
|
|
320 | 359 |
static void virtio_blk_handle_output(VirtIODevice *vdev, VirtQueue *vq) |
321 | 360 |
{ |
322 | 361 |
VirtIOBlock *s = to_virtio_blk(vdev); |
323 | 362 |
VirtIOBlockReq *req; |
324 |
BlockRequest blkreq[32]; |
|
325 |
int num_writes = 0; |
|
326 |
BlockDriverState *old_bs = NULL; |
|
363 |
MultiReqBuffer mrb = { |
|
364 |
.num_writes = 0, |
|
365 |
.old_bs = NULL, |
|
366 |
}; |
|
327 | 367 |
|
328 | 368 |
while ((req = virtio_blk_get_request(s))) { |
329 |
if (req->elem.out_num < 1 || req->elem.in_num < 1) { |
|
330 |
fprintf(stderr, "virtio-blk missing headers\n"); |
|
331 |
exit(1); |
|
332 |
} |
|
333 |
|
|
334 |
if (req->elem.out_sg[0].iov_len < sizeof(*req->out) || |
|
335 |
req->elem.in_sg[req->elem.in_num - 1].iov_len < sizeof(*req->in)) { |
|
336 |
fprintf(stderr, "virtio-blk header not in correct element\n"); |
|
337 |
exit(1); |
|
338 |
} |
|
339 |
|
|
340 |
req->out = (void *)req->elem.out_sg[0].iov_base; |
|
341 |
req->in = (void *)req->elem.in_sg[req->elem.in_num - 1].iov_base; |
|
342 |
|
|
343 |
if (req->out->type & VIRTIO_BLK_T_FLUSH) { |
|
344 |
virtio_blk_handle_flush(req); |
|
345 |
} else if (req->out->type & VIRTIO_BLK_T_SCSI_CMD) { |
|
346 |
virtio_blk_handle_scsi(req); |
|
347 |
} else if (req->out->type & VIRTIO_BLK_T_OUT) { |
|
348 |
qemu_iovec_init_external(&req->qiov, &req->elem.out_sg[1], |
|
349 |
req->elem.out_num - 1); |
|
350 |
virtio_blk_handle_write(blkreq, &num_writes, req, &old_bs); |
|
351 |
} else { |
|
352 |
qemu_iovec_init_external(&req->qiov, &req->elem.in_sg[0], |
|
353 |
req->elem.in_num - 1); |
|
354 |
virtio_blk_handle_read(req); |
|
355 |
} |
|
369 |
virtio_blk_handle_request(req, &mrb); |
|
356 | 370 |
} |
357 | 371 |
|
358 |
if (num_writes > 0) { |
|
359 |
do_multiwrite(old_bs, blkreq, num_writes);
|
|
372 |
if (mrb.num_writes > 0) {
|
|
373 |
do_multiwrite(mrb.old_bs, mrb.blkreq, mrb.num_writes);
|
|
360 | 374 |
} |
361 | 375 |
|
362 | 376 |
/* |
Also available in: Unified diff