From: Ronnie Sahlberg <ronniesahlberg@gmail.com>
To: pbonzini@redhat.com, qemu-devel@nongnu.org
Cc: Ronnie Sahlberg <ronniesahlberg@gmail.com>
Subject: [Qemu-devel] [PATCH] iSCSI: Add support for SG_IO in bdrv_ioctl()
Date: Tue, 21 Aug 2012 09:59:35 +1000 [thread overview]
Message-ID: <1345507175-7248-2-git-send-email-ronniesahlberg@gmail.com> (raw)
In-Reply-To: <1345507175-7248-1-git-send-email-ronniesahlberg@gmail.com>
We need to support SG_IO in the synchronous bdrv_ioctl() since this
is used by scsi-block
Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
---
block/iscsi.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 108 insertions(+), 1 deletions(-)
diff --git a/block/iscsi.c b/block/iscsi.c
index 993a86d..9e98bfe 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -548,7 +548,8 @@ iscsi_aio_ioctl_cb(struct iscsi_context *iscsi, int status,
#define SG_ERR_DRIVER_SENSE 0x08
- if (status == SCSI_STATUS_CHECK_CONDITION && acb->task->datain.size >= 2) {
+ if (status == SCSI_STATUS_CHECK_CONDITION
+ && acb->task->datain.size >= 2) {
int ss;
acb->ioh->driver_status |= SG_ERR_DRIVER_SENSE;
@@ -633,9 +634,53 @@ static BlockDriverAIOCB *iscsi_aio_ioctl(BlockDriverState *bs,
return &acb->common;
}
+struct IoctlTask {
+ int status;
+ int complete;
+ sg_io_hdr_t *ioh;
+ struct scsi_task *task;
+};
+
+static void
+iscsi_ioctl_cb(struct iscsi_context *iscsi, int status,
+ void *command_data, void *opaque)
+{
+ struct IoctlTask *itask = opaque;
+
+ if (status < 0) {
+ error_report("Failed to ioctl(SG_IO) to iSCSI lun. %s",
+ iscsi_get_error(iscsi));
+ itask->status = -EIO;
+ }
+
+ itask->ioh->driver_status = 0;
+ itask->ioh->host_status = 0;
+ itask->ioh->resid = 0;
+
+#define SG_ERR_DRIVER_SENSE 0x08
+
+ if (status == SCSI_STATUS_CHECK_CONDITION
+ && itask->task->datain.size >= 2) {
+ int ss;
+
+ itask->ioh->driver_status |= SG_ERR_DRIVER_SENSE;
+
+ itask->ioh->sb_len_wr = itask->task->datain.size - 2;
+ ss = (itask->ioh->mx_sb_len >= itask->ioh->sb_len_wr) ?
+ itask->ioh->mx_sb_len : itask->ioh->sb_len_wr;
+ memcpy(itask->ioh->sbp, &itask->task->datain.data[2], ss);
+ }
+
+ itask->complete = 1;
+}
+
static int iscsi_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
{
IscsiLun *iscsilun = bs->opaque;
+ struct iscsi_context *iscsi = iscsilun->iscsi;
+ struct IoctlTask itask;
+ struct scsi_task *task;
+ struct iscsi_data data;
switch (req) {
case SG_GET_VERSION_NUM:
@@ -644,6 +689,68 @@ static int iscsi_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
case SG_GET_SCSI_ID:
((struct sg_scsi_id *)buf)->scsi_type = iscsilun->type;
break;
+ case SG_IO:
+ itask.ioh = buf;
+ task = malloc(sizeof(struct scsi_task));
+ if (task == NULL) {
+ error_report("iSCSI: Failed to allocate task for scsi command. %s",
+ iscsi_get_error(iscsi));
+ return -1;
+ }
+ memset(task, 0, sizeof(struct scsi_task));
+
+ switch (itask.ioh->dxfer_direction) {
+ case SG_DXFER_TO_DEV:
+ task->xfer_dir = SCSI_XFER_WRITE;
+ break;
+ case SG_DXFER_FROM_DEV:
+ task->xfer_dir = SCSI_XFER_READ;
+ break;
+ default:
+ task->xfer_dir = SCSI_XFER_NONE;
+ break;
+ }
+ task->cdb_size = itask.ioh->cmd_len;
+ memcpy(&task->cdb[0], itask.ioh->cmdp, itask.ioh->cmd_len);
+ task->expxferlen = itask.ioh->dxfer_len;
+
+ if (task->xfer_dir == SCSI_XFER_WRITE) {
+ data.data = itask.ioh->dxferp;
+ data.size = itask.ioh->dxfer_len;
+ }
+
+ if (iscsi_scsi_command_async(iscsi, iscsilun->lun, task,
+ iscsi_ioctl_cb,
+ (task->xfer_dir == SCSI_XFER_WRITE) ?
+ &data : NULL,
+ &itask) != 0) {
+ scsi_free_scsi_task(task);
+ return -1;
+ }
+
+ /* tell libiscsi to read straight into the buffer we got from ioctl */
+ if (task->xfer_dir == SCSI_XFER_READ) {
+ scsi_task_add_data_in_buffer(task,
+ itask.ioh->dxfer_len,
+ itask.ioh->dxferp);
+ }
+
+ itask.complete = 0;
+ itask.status = 0;
+ itask.task = task;
+ while (!itask.complete) {
+ iscsi_set_events(iscsilun);
+ qemu_aio_wait();
+ }
+ scsi_free_scsi_task(task);
+
+ if (itask.status != 0) {
+ error_report("iSCSI: Failed to send async command to target : %s",
+ iscsi_get_error(iscsi));
+ return -1;
+ }
+
+ return 0;
default:
return -1;
}
--
1.7.3.1
next prev parent reply other threads:[~2012-08-20 23:59 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-08-20 23:59 [Qemu-devel] [PATCH] iSCSI: Add support for SG_IO to bdrv_ioctl()/iscsi_ioctl() Ronnie Sahlberg
2012-08-20 23:59 ` Ronnie Sahlberg [this message]
2012-08-21 7:00 ` [Qemu-devel] [PATCH] iSCSI: Add support for SG_IO in bdrv_ioctl() Paolo Bonzini
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1345507175-7248-2-git-send-email-ronniesahlberg@gmail.com \
--to=ronniesahlberg@gmail.com \
--cc=pbonzini@redhat.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).