All of lore.kernel.org
 help / color / mirror / Atom feed
From: Christoph Hellwig <hch@lst.de>
To: qemu@nongnu.org
Cc: Rusty Russell <rusty@rustcorp.com.au>,
	Hannes Reinecke <hare@suse.de>,
	Christian Borntraeger <borntraeger@de.ibm.com>,
	kvm@vger.kernel.org
Subject: [PATCH] virtio-blk: add SGI_IO passthru support
Date: Mon, 27 Apr 2009 10:26:07 +0200	[thread overview]
Message-ID: <20090427082606.GA32604@lst.de> (raw)

Add support for SG_IO passthru (packet commands) to the virtio-blk
backend.  Conceptually based on an older patch from Hannes Reinecke
but largely rewritten to match the code structure and layering in
virtio-blk.

Note that currently we issue the hose SG_IO synchronously.  We could
easily switch to async I/O, but that would required either bloating
the VirtIOBlockReq by the size of struct sg_io_hdr or an additional
memory allocation for each SG_IO request.


Signed-off-by: Christoph Hellwig <hch@lst.de>

Index: qemu/hw/virtio-blk.h
===================================================================
--- qemu.orig/hw/virtio-blk.h	2009-04-26 16:50:38.154074532 +0200
+++ qemu/hw/virtio-blk.h	2009-04-26 22:51:16.838076869 +0200
@@ -28,6 +28,9 @@
 #define VIRTIO_BLK_F_SIZE_MAX   1       /* Indicates maximum segment size */
 #define VIRTIO_BLK_F_SEG_MAX    2       /* Indicates maximum # of segments */
 #define VIRTIO_BLK_F_GEOMETRY   4       /* Indicates support of legacy geometry */
+#define VIRTIO_BLK_F_RO         5       /* Disk is read-only */
+#define VIRTIO_BLK_F_BLK_SIZE   6       /* Block size of disk is available*/
+#define VIRTIO_BLK_F_SCSI       7       /* Supports scsi command passthru */
 
 struct virtio_blk_config
 {
@@ -70,6 +73,15 @@ struct virtio_blk_inhdr
     unsigned char status;
 };
 
+/* SCSI pass-through header */
+struct virtio_scsi_inhdr
+{
+    uint32_t errors;
+    uint32_t data_len;
+    uint32_t sense_len;
+    uint32_t residual;
+};
+
 void *virtio_blk_init(PCIBus *bus, BlockDriverState *bs);
 
 #endif
Index: qemu/hw/virtio-blk.c
===================================================================
--- qemu.orig/hw/virtio-blk.c	2009-04-26 16:50:38.160074667 +0200
+++ qemu/hw/virtio-blk.c	2009-04-27 10:25:19.278074514 +0200
@@ -15,6 +15,9 @@
 #include <sysemu.h>
 #include "virtio-blk.h"
 #include "block_int.h"
+#ifdef __linux__
+# include <scsi/sg.h>
+#endif
 
 typedef struct VirtIOBlock
 {
@@ -35,6 +38,7 @@ typedef struct VirtIOBlockReq
     VirtQueueElement elem;
     struct virtio_blk_inhdr *in;
     struct virtio_blk_outhdr *out;
+    struct virtio_scsi_inhdr *scsi;
     QEMUIOVector qiov;
     struct VirtIOBlockReq *next;
 } VirtIOBlockReq;
@@ -103,6 +107,108 @@ static VirtIOBlockReq *virtio_blk_get_re
     return req;
 }
 
+#ifdef __linux__
+static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
+{
+    struct sg_io_hdr hdr;
+    int ret, size = 0;
+    int status;
+    int i;
+
+    /*
+     * We require at least one output segment each for the virtio_blk_outhdr
+     * and the SCSI command block.
+     *
+     * We also at least require the virtio_blk_inhdr, the virtio_scsi_inhdr
+     * and the sense buffer pointer in the input segments.
+     */
+    if (req->elem.out_num < 2 || req->elem.in_num < 3) {
+        virtio_blk_req_complete(req, VIRTIO_BLK_S_IOERR);
+        return;
+    }
+
+    /*
+     * No support for bidirection commands yet.
+     */
+    if (req->elem.out_num > 2 && req->elem.in_num > 3) {
+        virtio_blk_req_complete(req, VIRTIO_BLK_S_UNSUPP);
+        return;
+    }
+
+    /*
+     * The scsi inhdr is placed in the second-to-last input segment, just
+     * before the regular inhdr.
+     */
+    req->scsi = (void *)req->elem.in_sg[req->elem.in_num - 2].iov_base;
+    size = sizeof(*req->in) + sizeof(*req->scsi);
+
+    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.
+         */
+        hdr.dxfer_direction = SG_DXFER_TO_DEV;
+        hdr.iovec_count = req->elem.out_num - 2;
+
+        for (i = 0; i < hdr.iovec_count; i++)
+            hdr.dxfer_len += req->elem.out_sg[i + 2].iov_len;
+
+        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.
+         */
+        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;
+
+        hdr.dxferp = req->elem.in_sg;
+        size += hdr.dxfer_len;
+    } else {
+        /*
+         * Some SCSI commands don't actually transfer any data.
+         */
+        hdr.dxfer_direction = SG_DXFER_NONE;
+    }
+
+    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;
+
+    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;
+    }
+
+    req->scsi->errors = hdr.status;
+    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);
+}
+#else
+static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
+{
+    virtio_blk_req_complete(req, VIRTIO_BLK_S_UNSUPP);
+}
+#endif /* __linux__ */
+
 static void virtio_blk_handle_write(VirtIOBlockReq *req)
 {
     bdrv_aio_writev(req->dev->bs, req->out->sector, &req->qiov,
@@ -136,12 +242,7 @@ static void virtio_blk_handle_output(Vir
         req->in = (void *)req->elem.in_sg[req->elem.in_num - 1].iov_base;
 
         if (req->out->type & VIRTIO_BLK_T_SCSI_CMD) {
-            unsigned int len = sizeof(*req->in);
-
-            req->in->status = VIRTIO_BLK_S_UNSUPP;
-            virtqueue_push(vq, &req->elem, len);
-            virtio_notify(vdev, vq);
-            qemu_free(req);
+            virtio_blk_handle_scsi(req);
         } else if (req->out->type & VIRTIO_BLK_T_OUT) {
             qemu_iovec_init_external(&req->qiov, &req->elem.out_sg[1],
                                      req->elem.out_num - 1);
@@ -203,7 +304,15 @@ static void virtio_blk_update_config(Vir
 
 static uint32_t virtio_blk_get_features(VirtIODevice *vdev)
 {
-    return (1 << VIRTIO_BLK_F_SEG_MAX | 1 << VIRTIO_BLK_F_GEOMETRY);
+    uint32_t features = 0;
+
+    features |= (1 << VIRTIO_BLK_F_SEG_MAX);
+    features |= (1 << VIRTIO_BLK_F_GEOMETRY);
+#ifdef __linux__
+    features |= (1 << VIRTIO_BLK_F_SCSI);
+#endif
+
+    return features;
 }
 
 static void virtio_blk_save(QEMUFile *f, void *opaque)

             reply	other threads:[~2009-04-27  8:27 UTC|newest]

Thread overview: 50+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-04-27  8:26 Christoph Hellwig [this message]
2009-04-27  8:29 ` [PATCH] virtio-blk: add SGI_IO passthru support Christoph Hellwig
2009-04-27  8:29   ` [Qemu-devel] " Christoph Hellwig
2009-04-27  9:15   ` Avi Kivity
2009-04-27  9:15     ` [Qemu-devel] " Avi Kivity
2009-04-28  9:47     ` Christoph Hellwig
2009-04-28  9:47       ` Christoph Hellwig
2009-04-27 14:36   ` Anthony Liguori
2009-04-27 14:36     ` [Qemu-devel] " Anthony Liguori
2009-04-28  9:51     ` Christoph Hellwig
2009-04-28  9:51       ` Christoph Hellwig
2009-04-28 16:37       ` Anthony Liguori
2009-04-28 16:52         ` Christian Borntraeger
2009-04-28 16:52           ` Christian Borntraeger
2009-04-29 10:48         ` Christoph Hellwig
2009-04-29 10:48           ` Christoph Hellwig
2009-04-29 11:11           ` Paul Brook
2009-04-29 11:11             ` Paul Brook
2009-04-29 11:19             ` Christian Borntraeger
2009-04-29 11:19               ` Christian Borntraeger
2009-04-29 11:29               ` Paul Brook
2009-04-29 11:29                 ` Paul Brook
2009-04-29 11:21             ` Christoph Hellwig
2009-04-29 11:21               ` Christoph Hellwig
2009-04-29 11:37               ` Paul Brook
2009-04-29 11:37                 ` Paul Brook
2009-04-30 20:13                 ` Christoph Hellwig
2009-04-30 20:13                   ` Christoph Hellwig
2009-04-30 20:55                   ` Nicholas A. Bellinger
2009-04-30 20:55                     ` Nicholas A. Bellinger
2009-04-30 21:49                   ` Paul Brook
2009-04-30 21:49                     ` Paul Brook
2009-04-30 21:56                     ` Javier Guerra
2009-04-30 21:56                       ` Javier Guerra
2009-05-01  7:24                     ` Christoph Hellwig
2009-05-01  7:24                       ` Christoph Hellwig
2009-05-01 11:08                       ` Jamie Lokier
2009-05-01 11:08                         ` Jamie Lokier
2009-05-01 14:28                         ` Christoph Hellwig
2009-05-01 14:28                           ` Christoph Hellwig
2009-05-05  5:21                   ` Rusty Russell
2009-05-05  5:21                     ` Rusty Russell
2009-04-28 19:09       ` Christian Borntraeger
2009-04-28 19:09         ` Christian Borntraeger
2009-04-29 10:50         ` Christoph Hellwig
2009-04-29 10:50           ` Christoph Hellwig
2009-04-29 11:07           ` Christian Borntraeger
2009-04-29 11:07             ` Christian Borntraeger
2009-04-28  9:57   ` [PATCH 2/2] virtio-blk: add SG_IO " Christoph Hellwig
2009-04-28  9:57     ` [Qemu-devel] " Christoph Hellwig

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=20090427082606.GA32604@lst.de \
    --to=hch@lst.de \
    --cc=borntraeger@de.ibm.com \
    --cc=hare@suse.de \
    --cc=kvm@vger.kernel.org \
    --cc=qemu@nongnu.org \
    --cc=rusty@rustcorp.com.au \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.