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