diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c index 4ff64870bc..b5cc3855cf 100644 --- a/hw/block/virtio-blk.c +++ b/hw/block/virtio-blk.c @@ -27,6 +27,22 @@ #endif #include "hw/virtio/virtio-bus.h" +static VirtIOBlockReq *virtio_blk_alloc_request(VirtIOBlock *s) +{ + VirtIOBlockReq *req = g_slice_new0(VirtIOBlockReq); + req->dev = s; + req->elem = g_slice_new0(VirtQueueElement); + return req; +} + +static void virtio_blk_free_request(VirtIOBlockReq *req) +{ + if (req) { + g_slice_free(VirtQueueElement, req->elem); + g_slice_free(VirtIOBlockReq, req); + } +} + static void virtio_blk_req_complete(VirtIOBlockReq *req, int status) { VirtIOBlock *s = req->dev; @@ -35,7 +51,7 @@ static void virtio_blk_req_complete(VirtIOBlockReq *req, int status) trace_virtio_blk_req_complete(req, status); stb_p(&req->in->status, status); - virtqueue_push(s->vq, &req->elem, req->qiov.size + sizeof(*req->in)); + virtqueue_push(s->vq, req->elem, req->qiov.size + sizeof(*req->in)); virtio_notify(vdev, s->vq); } @@ -51,7 +67,7 @@ static int virtio_blk_handle_rw_error(VirtIOBlockReq *req, int error, } else if (action == BLOCK_ERROR_ACTION_REPORT) { virtio_blk_req_complete(req, VIRTIO_BLK_S_IOERR); bdrv_acct_done(s->bs, &req->acct); - g_free(req); + virtio_blk_free_request(req); } bdrv_error_action(s->bs, action, is_read, error); @@ -72,7 +88,7 @@ static void virtio_blk_rw_complete(void *opaque, int ret) virtio_blk_req_complete(req, VIRTIO_BLK_S_OK); bdrv_acct_done(req->dev->bs, &req->acct); - g_free(req); + virtio_blk_free_request(req); } static void virtio_blk_flush_complete(void *opaque, int ret) @@ -87,27 +103,16 @@ static void virtio_blk_flush_complete(void *opaque, int ret) virtio_blk_req_complete(req, VIRTIO_BLK_S_OK); bdrv_acct_done(req->dev->bs, &req->acct); - g_free(req); -} - -static VirtIOBlockReq *virtio_blk_alloc_request(VirtIOBlock *s) -{ - VirtIOBlockReq *req = g_malloc(sizeof(*req)); - req->dev = s; - req->qiov.size = 0; - req->next = NULL; - return req; + virtio_blk_free_request(req); } static VirtIOBlockReq *virtio_blk_get_request(VirtIOBlock *s) { VirtIOBlockReq *req = virtio_blk_alloc_request(s); - if (req != NULL) { - if (!virtqueue_pop(s->vq, &req->elem)) { - g_free(req); - return NULL; - } + if (!virtqueue_pop(s->vq, req->elem)) { + virtio_blk_free_request(req); + return NULL; } return req; @@ -236,9 +241,9 @@ static void virtio_blk_handle_scsi(VirtIOBlockReq *req) { int status; - status = virtio_blk_handle_scsi_req(req->dev, &req->elem); + status = virtio_blk_handle_scsi_req(req->dev, req->elem); virtio_blk_req_complete(req, status); - g_free(req); + virtio_blk_free_request(req); } typedef struct MultiReqBuffer { @@ -340,19 +345,19 @@ static void virtio_blk_handle_request(VirtIOBlockReq *req, { uint32_t type; - if (req->elem.out_num < 1 || req->elem.in_num < 1) { + if (req->elem->out_num < 1 || req->elem->in_num < 1) { error_report("virtio-blk missing headers"); exit(1); } - if (req->elem.out_sg[0].iov_len < sizeof(*req->out) || - req->elem.in_sg[req->elem.in_num - 1].iov_len < sizeof(*req->in)) { + if (req->elem->out_sg[0].iov_len < sizeof(*req->out) || + req->elem->in_sg[req->elem->in_num - 1].iov_len < sizeof(*req->in)) { error_report("virtio-blk header not in correct element"); exit(1); } - req->out = (void *)req->elem.out_sg[0].iov_base; - req->in = (void *)req->elem.in_sg[req->elem.in_num - 1].iov_base; + req->out = (void *)req->elem->out_sg[0].iov_base; + req->in = (void *)req->elem->in_sg[req->elem->in_num - 1].iov_base; type = ldl_p(&req->out->type); @@ -367,23 +372,23 @@ static void virtio_blk_handle_request(VirtIOBlockReq *req, * NB: per existing s/n string convention the string is * terminated by '\0' only when shorter than buffer. */ - strncpy(req->elem.in_sg[0].iov_base, + strncpy(req->elem->in_sg[0].iov_base, s->blk.serial ? s->blk.serial : "", - MIN(req->elem.in_sg[0].iov_len, VIRTIO_BLK_ID_BYTES)); + MIN(req->elem->in_sg[0].iov_len, VIRTIO_BLK_ID_BYTES)); virtio_blk_req_complete(req, VIRTIO_BLK_S_OK); - g_free(req); + virtio_blk_free_request(req); } else if (type & VIRTIO_BLK_T_OUT) { - qemu_iovec_init_external(&req->qiov, &req->elem.out_sg[1], - req->elem.out_num - 1); + qemu_iovec_init_external(&req->qiov, &req->elem->out_sg[1], + req->elem->out_num - 1); virtio_blk_handle_write(req, mrb); } else if (type == VIRTIO_BLK_T_IN || type == VIRTIO_BLK_T_BARRIER) { /* VIRTIO_BLK_T_IN is 0, so we can't just & it. */ - qemu_iovec_init_external(&req->qiov, &req->elem.in_sg[0], - req->elem.in_num - 1); + qemu_iovec_init_external(&req->qiov, &req->elem->in_sg[0], + req->elem->in_num - 1); virtio_blk_handle_read(req); } else { virtio_blk_req_complete(req, VIRTIO_BLK_S_UNSUPP); - g_free(req); + virtio_blk_free_request(req); } } @@ -598,7 +603,8 @@ static void virtio_blk_save(QEMUFile *f, void *opaque) while (req) { qemu_put_sbyte(f, 1); - qemu_put_buffer(f, (unsigned char*)&req->elem, sizeof(req->elem)); + qemu_put_buffer(f, (unsigned char *)req->elem, + sizeof(VirtQueueElement)); req = req->next; } qemu_put_sbyte(f, 0); @@ -620,14 +626,15 @@ static int virtio_blk_load(QEMUFile *f, void *opaque, int version_id) while (qemu_get_sbyte(f)) { VirtIOBlockReq *req = virtio_blk_alloc_request(s); - qemu_get_buffer(f, (unsigned char*)&req->elem, sizeof(req->elem)); + qemu_get_buffer(f, (unsigned char *)req->elem, + sizeof(VirtQueueElement)); req->next = s->rq; s->rq = req; - virtqueue_map_sg(req->elem.in_sg, req->elem.in_addr, - req->elem.in_num, 1); - virtqueue_map_sg(req->elem.out_sg, req->elem.out_addr, - req->elem.out_num, 0); + virtqueue_map_sg(req->elem->in_sg, req->elem->in_addr, + req->elem->in_num, 1); + virtqueue_map_sg(req->elem->out_sg, req->elem->out_addr, + req->elem->out_num, 0); } return 0; diff --git a/include/hw/virtio/virtio-blk.h b/include/hw/virtio/virtio-blk.h index d05d177ec5..b495e42d6d 100644 --- a/include/hw/virtio/virtio-blk.h +++ b/include/hw/virtio/virtio-blk.h @@ -136,7 +136,7 @@ typedef struct VirtIOBlock { typedef struct VirtIOBlockReq { VirtIOBlock *dev; - VirtQueueElement elem; + VirtQueueElement *elem; struct virtio_blk_inhdr *in; struct virtio_blk_outhdr *out; QEMUIOVector qiov;