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:
		@@ -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;
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user