From 97da65d63d0c6621054f3580aa51ff2677d47255 Mon Sep 17 00:00:00 2001 Message-Id: <97da65d63d0c6621054f3580aa51ff2677d47255.1429847625.git.jen@redhat.com> In-Reply-To: <67fe78a504035b7baf527bbd4726c75b0a1f8ba4.1429847625.git.jen@redhat.com> References: <67fe78a504035b7baf527bbd4726c75b0a1f8ba4.1429847625.git.jen@redhat.com> From: "Jeff E. Nelson" Date: Thu, 23 Apr 2015 17:38:11 -0500 Subject: [CHANGE 2/7] Revert: virtio-blk: Use blk_aio_ioctl To: rhvirt-patches@redhat.com, jen@redhat.com Patch was incorrectly applied from a superseded series. Signed-off-by: Jeff E. Nelson --- hw/virtio-blk.c | 122 +++++++++++++++++++++++++------------------------------- 1 file changed, 54 insertions(+), 68 deletions(-) diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c index 2e01ceb..298864a 100644 --- a/hw/virtio-blk.c +++ b/hw/virtio-blk.c @@ -152,54 +152,12 @@ static VirtIOBlockReq *virtio_blk_get_request(VirtIOBlock *s) } #ifdef __linux__ - -typedef struct { - VirtIOBlockReq *req; +static void virtio_blk_handle_scsi(VirtIOBlockReq *req) +{ struct sg_io_hdr hdr; -} VirtIOBlockIoctlReq; - -static void virtio_blk_ioctl_complete(void *opaque, int status) -{ - VirtIOBlockIoctlReq *ioctl_req = opaque; - VirtIOBlockReq *req = ioctl_req->req; - struct sg_io_hdr *hdr; - - if (status) { - status = VIRTIO_BLK_S_UNSUPP; - req->scsi->errors = 255; - goto out; - } - - hdr = &ioctl_req->hdr; - /* - * From SCSI-Generic-HOWTO: "Some lower level drivers (e.g. ide-scsi) - * clear the masked_status field [hence status gets cleared too, see - * block/scsi_ioctl.c] even when a CHECK_CONDITION or COMMAND_TERMINATED - * status has occurred. However they do set DRIVER_SENSE in driver_status - * field. Also a (sb_len_wr > 0) indicates there is a sense buffer. - */ - if (hdr->status == 0 && hdr->sb_len_wr > 0) { - hdr->status = CHECK_CONDITION; - } - - req->scsi->errors = hdr->status | (hdr->msg_status << 8) | - (hdr->host_status << 16) | (hdr->driver_status << 24); - req->scsi->residual = hdr->resid; - req->scsi->sense_len = hdr->sb_len_wr; - req->scsi->data_len = hdr->dxfer_len; - -out: - virtio_blk_req_complete(req, status); - qemu_free(req); - g_free(ioctl_req); -} - -static void virtio_blk_handle_scsi(VirtIOBlockReq *req) -{ - int size = 0; + int ret, size = 0; + int status; int i; - VirtIOBlockIoctlReq *ioctl_req; - VirtQueueElement *elem = &req->elem; if ((req->dev->vdev.guest_features & (1 << VIRTIO_BLK_F_SCSI)) == 0) { virtio_blk_req_complete(req, VIRTIO_BLK_S_UNSUPP); @@ -236,50 +194,78 @@ static void virtio_blk_handle_scsi(VirtIOBlockReq *req) req->scsi = (void *)req->elem.in_sg[req->elem.in_num - 2].iov_base; size = sizeof(*req->in) + sizeof(*req->scsi); - ioctl_req = g_new0(VirtIOBlockIoctlReq, 1); - ioctl_req->req = req; - ioctl_req->hdr.interface_id = 'S'; - ioctl_req->hdr.cmd_len = elem->out_sg[1].iov_len; - ioctl_req->hdr.cmdp = elem->out_sg[1].iov_base; - ioctl_req->hdr.dxfer_len = 0; + memset(&hdr, 0, sizeof(struct sg_io_hdr)); + hdr.interface_id = 'S'; + hdr.cmd_len = req->elem.out_sg[1].iov_len; + hdr.cmdp = req->elem.out_sg[1].iov_base; + hdr.dxfer_len = 0; if (req->elem.out_num > 2) { /* * If there are more than the minimally required 2 output segments * there is write payload starting from the third iovec. */ - ioctl_req->hdr.dxfer_direction = SG_DXFER_TO_DEV; - ioctl_req->hdr.iovec_count = req->elem.out_num - 2; + hdr.dxfer_direction = SG_DXFER_TO_DEV; + hdr.iovec_count = req->elem.out_num - 2; - for (i = 0; i < ioctl_req->hdr.iovec_count; i++) - ioctl_req->hdr.dxfer_len += req->elem.out_sg[i + 2].iov_len; + for (i = 0; i < hdr.iovec_count; i++) + hdr.dxfer_len += req->elem.out_sg[i + 2].iov_len; - ioctl_req->hdr.dxferp = req->elem.out_sg + 2; + hdr.dxferp = req->elem.out_sg + 2; } else if (req->elem.in_num > 3) { /* * If we have more than 3 input segments the guest wants to actually * read data. */ - ioctl_req->hdr.dxfer_direction = SG_DXFER_FROM_DEV; - ioctl_req->hdr.iovec_count = req->elem.in_num - 3; - for (i = 0; i < ioctl_req->hdr.iovec_count; i++) - ioctl_req->hdr.dxfer_len += req->elem.in_sg[i].iov_len; + hdr.dxfer_direction = SG_DXFER_FROM_DEV; + hdr.iovec_count = req->elem.in_num - 3; + for (i = 0; i < hdr.iovec_count; i++) + hdr.dxfer_len += req->elem.in_sg[i].iov_len; - ioctl_req->hdr.dxferp = req->elem.in_sg; - size += ioctl_req->hdr.dxfer_len; + hdr.dxferp = req->elem.in_sg; + size += hdr.dxfer_len; } else { /* * Some SCSI commands don't actually transfer any data. */ - ioctl_req->hdr.dxfer_direction = SG_DXFER_NONE; + hdr.dxfer_direction = SG_DXFER_NONE; } - ioctl_req->hdr.sbp = req->elem.in_sg[req->elem.in_num - 3].iov_base; - ioctl_req->hdr.mx_sb_len = req->elem.in_sg[req->elem.in_num - 3].iov_len; + hdr.sbp = req->elem.in_sg[req->elem.in_num - 3].iov_base; + hdr.mx_sb_len = req->elem.in_sg[req->elem.in_num - 3].iov_len; + size += hdr.mx_sb_len; - bdrv_aio_ioctl(req->dev->bs, SG_IO, &ioctl_req->hdr, - virtio_blk_ioctl_complete, ioctl_req); + ret = bdrv_ioctl(req->dev->bs, SG_IO, &hdr); + if (ret) { + status = VIRTIO_BLK_S_UNSUPP; + hdr.status = ret; + hdr.resid = hdr.dxfer_len; + } else if (hdr.status) { + status = VIRTIO_BLK_S_IOERR; + } else { + status = VIRTIO_BLK_S_OK; + } + + /* + * From SCSI-Generic-HOWTO: "Some lower level drivers (e.g. ide-scsi) + * clear the masked_status field [hence status gets cleared too, see + * block/scsi_ioctl.c] even when a CHECK_CONDITION or COMMAND_TERMINATED + * status has occurred. However they do set DRIVER_SENSE in driver_status + * field. Also a (sb_len_wr > 0) indicates there is a sense buffer. + */ + if (hdr.status == 0 && hdr.sb_len_wr > 0) { + hdr.status = CHECK_CONDITION; + } + + req->scsi->errors = hdr.status | (hdr.msg_status << 8) | + (hdr.host_status << 16) | (hdr.driver_status << 24); + req->scsi->residual = hdr.resid; + req->scsi->sense_len = hdr.sb_len_wr; + req->scsi->data_len = hdr.dxfer_len; + + virtio_blk_req_complete(req, status); + qemu_free(req); } #else static void virtio_blk_handle_scsi(VirtIOBlockReq *req) -- 2.1.0