qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH 2/4] virtio-scsi: Add basic request processing i


From: Zhi Yong Wu
Subject: Re: [Qemu-devel] [PATCH 2/4] virtio-scsi: Add basic request processing infrastructure
Date: Wed, 16 Nov 2011 16:28:05 +0800

On Wed, Nov 16, 2011 at 1:00 AM, Paolo Bonzini <address@hidden> wrote:
> From: Stefan Hajnoczi <address@hidden>
>
> Signed-off-by: Stefan Hajnoczi <address@hidden>
> Signed-off-by: Paolo Bonzini <address@hidden>
> ---
>  hw/virtio-scsi.c |  138 
> +++++++++++++++++++++++++++++++++++++++++++++++++++++-
>  1 files changed, 136 insertions(+), 2 deletions(-)
>
> diff --git a/hw/virtio-scsi.c b/hw/virtio-scsi.c
> index ff86376..7e6348a 100644
> --- a/hw/virtio-scsi.c
> +++ b/hw/virtio-scsi.c
> @@ -127,14 +127,148 @@ typedef struct {
>     uint32_t cdb_size;
>  } VirtIOSCSI;
>
> +typedef struct VirtIOSCSIReq {
> +    struct VirtIOSCSIReq *next;
> +    VirtIOSCSI *dev;
> +    VirtQueue *vq;
> +    VirtQueueElement elem;
> +    QEMUSGList qsgl;
> +    SCSIRequest *sreq;
> +    union {
> +        char                  *buf;
> +        VirtIOSCSICmdReq      *cmd;
> +        VirtIOSCSICtrlTMFReq  *tmf;
> +        VirtIOSCSICtrlANReq   *an;
> +    } req;
> +    union {
> +        char                  *buf;
> +        VirtIOSCSICmdResp     *cmd;
> +        VirtIOSCSICtrlTMFResp *tmf;
> +        VirtIOSCSICtrlANResp  *an;
> +        VirtIOSCSIEvent       *event;
> +    } resp;
> +} VirtIOSCSIReq;
> +
> +static void virtio_scsi_complete_req(VirtIOSCSIReq *req)
> +{
> +    VirtQueue *vq = req->vq;
> +    virtqueue_push(vq, &req->elem, req->qsgl.size + 
> req->elem.in_sg[0].iov_len);
> +    qemu_sglist_destroy(&req->qsgl);
> +    if (req->sreq) {
> +        req->sreq->hba_private = NULL;
> +        scsi_req_unref(req->sreq);
> +    }
> +    g_free(req);
> +    virtio_notify(&req->dev->vdev, vq);
req is used-after-free?
> +}
> +
> +static void virtio_scsi_bad_req(void)
> +{
> +    error_report("wrong size for virtio-scsi headers");
> +    exit(1);
> +}
> +
> +static void qemu_sgl_init_external(QEMUSGList *qsgl, struct iovec *sg,
> +                                   target_phys_addr_t *addr, int num)
> +{
> +    memset(qsgl, 0, sizeof(*qsgl));
> +    while (num--) {
> +        qemu_sglist_add(qsgl, *(addr++), (sg++)->iov_len);
> +    }
> +}
> +
> +static VirtIOSCSIReq *virtio_scsi_parse_req(VirtIOSCSI *s, VirtQueue *vq)
> +{
> +    VirtIOSCSIReq *req;
> +    req = g_malloc(sizeof(*req));
> +    if (!virtqueue_pop(vq, &req->elem)) {
> +        g_free(req);
> +        return NULL;
> +    }
> +
> +    assert(req->elem.out_num && req->elem.in_num);
> +    req->vq = vq;
> +    req->dev = s;
> +    req->next = NULL;
> +    req->sreq = NULL;
> +    req->req.buf = req->elem.out_sg[0].iov_base;
> +    req->resp.buf = req->elem.in_sg[0].iov_base;
> +
> +    if (req->elem.out_num > 1) {
> +        qemu_sgl_init_external(&req->qsgl, &req->elem.out_sg[1],
> +                               &req->elem.out_addr[1],
> +                               req->elem.out_num - 1);
> +    } else {
> +        qemu_sgl_init_external(&req->qsgl, &req->elem.in_sg[1],
> +                               &req->elem.in_addr[1],
> +                               req->elem.in_num - 1);
> +    }
> +
> +    return req;
> +}
> +
> +static void virtio_scsi_fail_ctrl_req(VirtIOSCSI *s, VirtIOSCSIReq *req)
> +{
> +    if (req->req.tmf->type == VIRTIO_SCSI_T_TMF) {
> +        req->resp.tmf->response = VIRTIO_SCSI_S_FAILURE;
> +    } else {
> +        req->resp.an->response = VIRTIO_SCSI_S_FAILURE;
> +    }
> +
> +    virtio_scsi_complete_req(req);
> +}
> +
>  static void virtio_scsi_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
>  {
> -    /* TODO */
> +    VirtIOSCSI *s = (VirtIOSCSI *)vdev;
> +    VirtIOSCSIReq *req;
> +
> +    while ((req = virtio_scsi_parse_req(s, vq))) {
> +        virtio_scsi_fail_ctrl_req(s, req);
> +    }
> +}
> +
> +static void virtio_scsi_fail_cmd_req(VirtIOSCSI *s, VirtIOSCSIReq *req)
> +{
> +    req->resp.cmd->response = VIRTIO_SCSI_S_FAILURE;
> +    virtio_scsi_complete_req(req);
>  }
>
>  static void virtio_scsi_handle_cmd(VirtIODevice *vdev, VirtQueue *vq)
>  {
> -    /* TODO */
> +    VirtIOSCSI *s = (VirtIOSCSI *)vdev;
> +    VirtIOSCSIReq *req;
> +
> +    while ((req = virtio_scsi_parse_req(s, vq))) {
> +        int out_size, in_size;
> +        if (req->elem.out_num < 1 || req->elem.in_num < 1) {
> +            virtio_scsi_bad_req();
> +        }
> +
> +        out_size = req->elem.out_sg[0].iov_len;
> +        in_size = req->elem.in_sg[0].iov_len;
> +        if (out_size < sizeof(VirtIOSCSICmdReq) + VIRTIO_SCSI_CDB_SIZE ||
> +            in_size < sizeof(VirtIOSCSICmdResp) + VIRTIO_SCSI_SENSE_SIZE) {
> +            virtio_scsi_bad_req();
> +        }
> +
> +        if (req->elem.out_num > 1 && req->elem.in_num > 1) {
> +            virtio_scsi_fail_cmd_req(s, req);
> +            continue;
> +        }
> +
> +        req->resp.cmd->resid = 0;
> +        req->resp.cmd->status_qualifier = 0;
> +        req->resp.cmd->status = CHECK_CONDITION;
> +        req->resp.cmd->sense_len = 4;
> +        req->resp.cmd->sense[0] = 0xf0; /* Fixed format current sense */
> +        req->resp.cmd->sense[1] = ILLEGAL_REQUEST;
> +        req->resp.cmd->sense[2] = 0x20;
> +        req->resp.cmd->sense[3] = 0x00;
> +        req->resp.cmd->response = VIRTIO_SCSI_S_OK;
> +
> +        virtio_scsi_complete_req(req);
> +    }
>  }
>
>  static void virtio_scsi_get_config(VirtIODevice *vdev,
> --
> 1.7.7.1
>
>
>
>



-- 
Regards,

Zhi Yong Wu



reply via email to

[Prev in Thread] Current Thread [Next in Thread]