virtio-blk: Convert VirtIOBlockReq.elem to pointer

This will make converging with dataplane code easier.

Add virtio_blk_free_request to handle the freeing of request internal
fields.

Signed-off-by: Fam Zheng <famz@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
Fam Zheng 2014-06-11 12:11:43 +08:00 committed by Kevin Wolf
parent 09f6458770
commit 671ec3f056
2 changed files with 47 additions and 40 deletions

View file

@ -27,6 +27,22 @@
#endif #endif
#include "hw/virtio/virtio-bus.h" #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) static void virtio_blk_req_complete(VirtIOBlockReq *req, int status)
{ {
VirtIOBlock *s = req->dev; 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); trace_virtio_blk_req_complete(req, status);
stb_p(&req->in->status, 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); 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) { } else if (action == BLOCK_ERROR_ACTION_REPORT) {
virtio_blk_req_complete(req, VIRTIO_BLK_S_IOERR); virtio_blk_req_complete(req, VIRTIO_BLK_S_IOERR);
bdrv_acct_done(s->bs, &req->acct); bdrv_acct_done(s->bs, &req->acct);
g_free(req); virtio_blk_free_request(req);
} }
bdrv_error_action(s->bs, action, is_read, error); 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); virtio_blk_req_complete(req, VIRTIO_BLK_S_OK);
bdrv_acct_done(req->dev->bs, &req->acct); 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) 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); virtio_blk_req_complete(req, VIRTIO_BLK_S_OK);
bdrv_acct_done(req->dev->bs, &req->acct); bdrv_acct_done(req->dev->bs, &req->acct);
g_free(req); virtio_blk_free_request(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;
} }
static VirtIOBlockReq *virtio_blk_get_request(VirtIOBlock *s) static VirtIOBlockReq *virtio_blk_get_request(VirtIOBlock *s)
{ {
VirtIOBlockReq *req = virtio_blk_alloc_request(s); VirtIOBlockReq *req = virtio_blk_alloc_request(s);
if (req != NULL) { if (!virtqueue_pop(s->vq, req->elem)) {
if (!virtqueue_pop(s->vq, &req->elem)) { virtio_blk_free_request(req);
g_free(req); return NULL;
return NULL;
}
} }
return req; return req;
@ -236,9 +241,9 @@ static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
{ {
int status; 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); virtio_blk_req_complete(req, status);
g_free(req); virtio_blk_free_request(req);
} }
typedef struct MultiReqBuffer { typedef struct MultiReqBuffer {
@ -340,19 +345,19 @@ static void virtio_blk_handle_request(VirtIOBlockReq *req,
{ {
uint32_t type; 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"); error_report("virtio-blk missing headers");
exit(1); exit(1);
} }
if (req->elem.out_sg[0].iov_len < sizeof(*req->out) || 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)) { req->elem->in_sg[req->elem->in_num - 1].iov_len < sizeof(*req->in)) {
error_report("virtio-blk header not in correct element"); error_report("virtio-blk header not in correct element");
exit(1); exit(1);
} }
req->out = (void *)req->elem.out_sg[0].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; req->in = (void *)req->elem->in_sg[req->elem->in_num - 1].iov_base;
type = ldl_p(&req->out->type); 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 * NB: per existing s/n string convention the string is
* terminated by '\0' only when shorter than buffer. * 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 : "", 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); virtio_blk_req_complete(req, VIRTIO_BLK_S_OK);
g_free(req); virtio_blk_free_request(req);
} else if (type & VIRTIO_BLK_T_OUT) { } else if (type & VIRTIO_BLK_T_OUT) {
qemu_iovec_init_external(&req->qiov, &req->elem.out_sg[1], qemu_iovec_init_external(&req->qiov, &req->elem->out_sg[1],
req->elem.out_num - 1); req->elem->out_num - 1);
virtio_blk_handle_write(req, mrb); virtio_blk_handle_write(req, mrb);
} else if (type == VIRTIO_BLK_T_IN || type == VIRTIO_BLK_T_BARRIER) { } else if (type == VIRTIO_BLK_T_IN || type == VIRTIO_BLK_T_BARRIER) {
/* VIRTIO_BLK_T_IN is 0, so we can't just & it. */ /* VIRTIO_BLK_T_IN is 0, so we can't just & it. */
qemu_iovec_init_external(&req->qiov, &req->elem.in_sg[0], qemu_iovec_init_external(&req->qiov, &req->elem->in_sg[0],
req->elem.in_num - 1); req->elem->in_num - 1);
virtio_blk_handle_read(req); virtio_blk_handle_read(req);
} else { } else {
virtio_blk_req_complete(req, VIRTIO_BLK_S_UNSUPP); 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) { while (req) {
qemu_put_sbyte(f, 1); 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; req = req->next;
} }
qemu_put_sbyte(f, 0); 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)) { while (qemu_get_sbyte(f)) {
VirtIOBlockReq *req = virtio_blk_alloc_request(s); 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; req->next = s->rq;
s->rq = req; s->rq = req;
virtqueue_map_sg(req->elem.in_sg, req->elem.in_addr, virtqueue_map_sg(req->elem->in_sg, req->elem->in_addr,
req->elem.in_num, 1); req->elem->in_num, 1);
virtqueue_map_sg(req->elem.out_sg, req->elem.out_addr, virtqueue_map_sg(req->elem->out_sg, req->elem->out_addr,
req->elem.out_num, 0); req->elem->out_num, 0);
} }
return 0; return 0;

View file

@ -136,7 +136,7 @@ typedef struct VirtIOBlock {
typedef struct VirtIOBlockReq { typedef struct VirtIOBlockReq {
VirtIOBlock *dev; VirtIOBlock *dev;
VirtQueueElement elem; VirtQueueElement *elem;
struct virtio_blk_inhdr *in; struct virtio_blk_inhdr *in;
struct virtio_blk_outhdr *out; struct virtio_blk_outhdr *out;
QEMUIOVector qiov; QEMUIOVector qiov;