qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [RFC PATCH 0/4] virtio-scsi device model
@ 2011-11-15 17:00 Paolo Bonzini
  2011-11-15 17:00 ` [Qemu-devel] [PATCH 1/4] virtio-scsi: Add virtio-scsi stub device Paolo Bonzini
                   ` (4 more replies)
  0 siblings, 5 replies; 9+ messages in thread
From: Paolo Bonzini @ 2011-11-15 17:00 UTC (permalink / raw)
  To: qemu-devel; +Cc: stefanha, mst

Here is the first sneak peek of virtio-scsi.  It's on top of my scsi-sg
branch at http://github.com/bonzini/qemu.  I'm more interested
in getting early reviews in the virtio side, so I'm omitting the
scsi-specific patches that introduce support for scatter/gather I/O
in the SCSI layer.

What's missing is 1) support for writable config space, 2) testing TMF,
3) events; 4) migration.  The last two do not need to be in at the
first commit, they can come later.

Tested lightly with a seabios driver (see the seabios ML).  The Linux
driver will come next...

Paolo Bonzini (2):
  virtio-scsi: add basic SCSI bus operation
  virtio-scsi: process control queue requests

Stefan Hajnoczi (2):
  virtio-scsi: Add virtio-scsi stub device
  virtio-scsi: Add basic request processing infrastructure

 Makefile.target         |    1 +
 default-configs/pci.mak |    1 +
 hw/pci.h                |    1 +
 hw/virtio-pci.c         |   42 ++++
 hw/virtio-pci.h         |    2 +
 hw/virtio-scsi.c        |  502 +++++++++++++++++++++++++++++++++++++++++++++++
 hw/virtio-scsi.h        |   28 +++
 hw/virtio.h             |    3 +
 8 files changed, 580 insertions(+), 0 deletions(-)
 create mode 100644 hw/virtio-scsi.c
 create mode 100644 hw/virtio-scsi.h

-- 
1.7.7.1

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [Qemu-devel] [PATCH 1/4] virtio-scsi: Add virtio-scsi stub device
  2011-11-15 17:00 [Qemu-devel] [RFC PATCH 0/4] virtio-scsi device model Paolo Bonzini
@ 2011-11-15 17:00 ` Paolo Bonzini
  2011-11-15 17:00 ` [Qemu-devel] [PATCH 2/4] virtio-scsi: Add basic request processing infrastructure Paolo Bonzini
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 9+ messages in thread
From: Paolo Bonzini @ 2011-11-15 17:00 UTC (permalink / raw)
  To: qemu-devel; +Cc: stefanha, mst

From: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>

Add a useless virtio SCSI HBA device:

  qemu -device virtio-scsi-pci

Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 Makefile.target         |    1 +
 default-configs/pci.mak |    1 +
 hw/pci.h                |    1 +
 hw/virtio-pci.c         |   42 ++++++++++
 hw/virtio-pci.h         |    2 +
 hw/virtio-scsi.c        |  194 +++++++++++++++++++++++++++++++++++++++++++++++
 hw/virtio-scsi.h        |   28 +++++++
 hw/virtio.h             |    3 +
 8 files changed, 272 insertions(+), 0 deletions(-)
 create mode 100644 hw/virtio-scsi.c
 create mode 100644 hw/virtio-scsi.h

diff --git a/Makefile.target b/Makefile.target
index a111521..f3bc562 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -199,6 +199,7 @@ obj-y = arch_init.o cpus.o monitor.o machine.o gdbstub.o balloon.o ioport.o
 # need to fix this properly
 obj-$(CONFIG_NO_PCI) += pci-stub.o
 obj-$(CONFIG_VIRTIO) += virtio.o virtio-blk.o virtio-balloon.o virtio-net.o virtio-serial-bus.o
+obj-$(CONFIG_VIRTIO_SCSI) += virtio-scsi.o
 obj-y += vhost_net.o
 obj-$(CONFIG_VHOST_NET) += vhost.o
 obj-$(CONFIG_REALLY_VIRTFS) += 9pfs/virtio-9p-device.o
diff --git a/default-configs/pci.mak b/default-configs/pci.mak
index 22bd350..9c8edd4 100644
--- a/default-configs/pci.mak
+++ b/default-configs/pci.mak
@@ -1,5 +1,6 @@
 CONFIG_PCI=y
 CONFIG_VIRTIO_PCI=y
+CONFIG_VIRTIO_SCSI=y
 CONFIG_VIRTIO=y
 CONFIG_USB_UHCI=y
 CONFIG_USB_OHCI=y
diff --git a/hw/pci.h b/hw/pci.h
index 4b2e785..e21ffd2 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -75,6 +75,7 @@
 #define PCI_DEVICE_ID_VIRTIO_BLOCK       0x1001
 #define PCI_DEVICE_ID_VIRTIO_BALLOON     0x1002
 #define PCI_DEVICE_ID_VIRTIO_CONSOLE     0x1003
+#define PCI_DEVICE_ID_VIRTIO_SCSI        0x1004
 
 #define FMT_PCIBUS                      PRIx64
 
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index ca5923c..72be056 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -19,6 +19,7 @@
 #include "virtio-blk.h"
 #include "virtio-net.h"
 #include "virtio-serial.h"
+#include "virtio-scsi.h"
 #include "pci.h"
 #include "qemu-error.h"
 #include "msix.h"
@@ -784,6 +785,32 @@ static int virtio_balloon_exit_pci(PCIDevice *pci_dev)
     return virtio_exit_pci(pci_dev);
 }
 
+static int virtio_scsi_init_pci(PCIDevice *pci_dev)
+{
+    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
+    VirtIODevice *vdev;
+
+    vdev = virtio_scsi_init(&pci_dev->qdev, &proxy->scsi);
+    if (!vdev) {
+        return -EINVAL;
+    }
+
+    vdev->nvectors = proxy->nvectors;
+    virtio_init_pci(proxy, vdev);
+
+    /* make the actual value visible */
+    proxy->nvectors = vdev->nvectors;
+    return 0;
+}
+
+static int virtio_scsi_exit_pci(PCIDevice *pci_dev)
+{
+    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
+
+    virtio_scsi_exit(proxy->vdev);
+    return virtio_exit_pci(pci_dev);
+}
+
 static PCIDeviceInfo virtio_info[] = {
     {
         .qdev.name = "virtio-blk-pci",
@@ -869,6 +896,21 @@ static PCIDeviceInfo virtio_info[] = {
         },
         .qdev.reset = virtio_pci_reset,
     },{
+        .qdev.name = "virtio-scsi-pci",
+        .qdev.size = sizeof(VirtIOPCIProxy),
+        .init      = virtio_scsi_init_pci,
+        .exit      = virtio_scsi_exit_pci,
+        .vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET,
+        .device_id = PCI_DEVICE_ID_VIRTIO_SCSI,
+        .class_id  = PCI_CLASS_STORAGE_SCSI,
+        .revision  = 0x00,
+        .qdev.props = (Property[]) {
+            DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
+            DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
+            DEFINE_PROP_UINT32("num_queues", VirtIOPCIProxy, scsi.num_queues, 1),
+            DEFINE_PROP_END_OF_LIST(),
+        },
+    }, {
         /* end of list */
     }
 };
diff --git a/hw/virtio-pci.h b/hw/virtio-pci.h
index f8404de..20523af 100644
--- a/hw/virtio-pci.h
+++ b/hw/virtio-pci.h
@@ -17,6 +17,7 @@
 
 #include "virtio-net.h"
 #include "virtio-serial.h"
+#include "virtio-scsi.h"
 
 /* Performance improves when virtqueue kick processing is decoupled from the
  * vcpu thread using ioeventfd for some devices. */
@@ -40,6 +41,7 @@ typedef struct {
 #endif
     virtio_serial_conf serial;
     virtio_net_conf net;
+    VirtIOSCSIConf scsi;
     bool ioeventfd_disabled;
     bool ioeventfd_started;
 } VirtIOPCIProxy;
diff --git a/hw/virtio-scsi.c b/hw/virtio-scsi.c
new file mode 100644
index 0000000..ff86376
--- /dev/null
+++ b/hw/virtio-scsi.c
@@ -0,0 +1,194 @@
+/*
+ * Virtio SCSI HBA
+ *
+ * Copyright IBM, Corp. 2010
+ * Copyright Red Hat, Inc. 2011
+ *
+ * Authors:
+ *   Stefan Hajnoczi    <stefanha@linux.vnet.ibm.com>
+ *   Paolo Bonzini      <pbonzini@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#include "virtio-scsi.h"
+#include <hw/scsi.h>
+#include <hw/scsi-defs.h>
+
+#define VIRTIO_SCSI_VQ_SIZE    128
+#define VIRTIO_SCSI_CDB_SIZE   32
+#define VIRTIO_SCSI_SENSE_SIZE 96
+
+/* Response codes */
+#define VIRTIO_SCSI_S_OK                       0
+#define VIRTIO_SCSI_S_UNDERRUN                 1
+#define VIRTIO_SCSI_S_ABORTED                  2
+#define VIRTIO_SCSI_S_BAD_TARGET               3
+#define VIRTIO_SCSI_S_RESET                    4
+#define VIRTIO_SCSI_S_TRANSPORT_FAILURE        5
+#define VIRTIO_SCSI_S_TARGET_FAILURE           6
+#define VIRTIO_SCSI_S_NEXUS_FAILURE            7
+#define VIRTIO_SCSI_S_FAILURE                  8
+#define VIRTIO_SCSI_S_FUNCTION_SUCCEEDED       9
+#define VIRTIO_SCSI_S_FUNCTION_REJECTED        10
+#define VIRTIO_SCSI_S_INCORRECT_LUN            11
+
+/* Controlq type codes.  */
+#define VIRTIO_SCSI_T_TMF                      0
+#define VIRTIO_SCSI_T_AN_QUERY                 1
+#define VIRTIO_SCSI_T_AN_SUBSCRIBE             2
+
+/* Valid TMF subtypes.  */
+#define VIRTIO_SCSI_T_TMF_ABORT_TASK           0
+#define VIRTIO_SCSI_T_TMF_ABORT_TASK_SET       1
+#define VIRTIO_SCSI_T_TMF_CLEAR_ACA            2
+#define VIRTIO_SCSI_T_TMF_CLEAR_TASK_SET       3
+#define VIRTIO_SCSI_T_TMF_I_T_NEXUS_RESET      4
+#define VIRTIO_SCSI_T_TMF_LOGICAL_UNIT_RESET   5
+#define VIRTIO_SCSI_T_TMF_QUERY_TASK           6
+#define VIRTIO_SCSI_T_TMF_QUERY_TASK_SET       7
+
+/* Events.  */
+#define VIRTIO_SCSI_T_EVENTS_MISSED            0x80000000
+#define VIRTIO_SCSI_T_NO_EVENT                 0
+#define VIRTIO_SCSI_T_TRANSPORT_RESET          1
+#define VIRTIO_SCSI_T_ASYNC_NOTIFY             2
+
+/* SCSI command request, followed by data-out */
+typedef struct {
+    uint8_t lun[8];              /* Logical Unit Number */
+    uint64_t tag;                /* Command identifier */
+    uint8_t task_attr;           /* Task attribute */
+    uint8_t prio;
+    uint8_t crn;
+    uint8_t cdb[];
+} QEMU_PACKED VirtIOSCSICmdReq;
+
+/* Response, followed by sense data and data-in */
+typedef struct {
+    uint32_t sense_len;          /* Sense data length */
+    uint32_t resid;              /* Residual bytes in data buffer */
+    uint16_t status_qualifier;   /* Status qualifier */
+    uint8_t status;              /* Command completion status */
+    uint8_t response;            /* Response values */
+    uint8_t sense[];
+} QEMU_PACKED VirtIOSCSICmdResp;
+
+/* Task Management Request */
+typedef struct {
+    uint32_t type;
+    uint32_t subtype;
+    uint8_t lun[8];
+    uint64_t tag;
+} QEMU_PACKED VirtIOSCSICtrlTMFReq;
+
+typedef struct {
+    uint8_t response;
+} QEMU_PACKED VirtIOSCSICtrlTMFResp;
+
+/* Asynchronous notification query/subscription */
+typedef struct {
+    uint32_t type;
+    uint8_t lun[8];
+    uint32_t event_requested;
+} QEMU_PACKED VirtIOSCSICtrlANReq;
+
+typedef struct {
+    uint32_t event_actual;
+    uint8_t response;
+} QEMU_PACKED VirtIOSCSICtrlANResp;
+
+typedef struct {
+    uint32_t event;
+    uint8_t lun[8];
+    uint32_t reason;
+} QEMU_PACKED VirtIOSCSIEvent;
+
+typedef struct {
+    uint32_t num_queues;
+    uint32_t seg_max;
+    uint32_t event_info_size;
+    uint32_t sense_size;
+    uint32_t cdb_size;
+} QEMU_PACKED VirtIOSCSIConfig;
+
+typedef struct {
+    VirtIODevice vdev;
+    DeviceState *qdev;
+    VirtIOSCSIConf *conf;
+
+    VirtQueue *ctrl_vq;
+    VirtQueue *event_vq;
+    VirtQueue *cmd_vq;
+    uint32_t event_info_size;
+    uint32_t sense_size;
+    uint32_t cdb_size;
+} VirtIOSCSI;
+
+static void virtio_scsi_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
+{
+    /* TODO */
+}
+
+static void virtio_scsi_handle_cmd(VirtIODevice *vdev, VirtQueue *vq)
+{
+    /* TODO */
+}
+
+static void virtio_scsi_get_config(VirtIODevice *vdev,
+                                   uint8_t *config)
+{
+    VirtIOSCSIConfig *scsiconf = (VirtIOSCSIConfig *)config;
+    VirtIOSCSI *s = (VirtIOSCSI *)vdev;
+
+    stl_raw(&scsiconf->num_queues, s->conf->num_queues);
+    stl_raw(&scsiconf->seg_max, 128 - 2);
+    stl_raw(&scsiconf->event_info_size, s->event_info_size);
+    stl_raw(&scsiconf->sense_size, s->sense_size);
+    stl_raw(&scsiconf->cdb_size, s->cdb_size);
+}
+
+static uint32_t virtio_scsi_get_features(VirtIODevice *vdev,
+                                         uint32_t requested_features)
+{
+    return requested_features;
+}
+
+VirtIODevice *virtio_scsi_init(DeviceState *dev, VirtIOSCSIConf *proxyconf)
+{
+    VirtIOSCSI *s;
+
+    s = (VirtIOSCSI *)virtio_common_init("virtio-scsi", VIRTIO_ID_SCSI,
+                                         sizeof(VirtIOSCSIConf),
+                                         sizeof(VirtIOSCSI));
+
+    s->qdev = dev;
+    s->conf = proxyconf;
+
+    /* TODO set up vdev function pointers */
+    s->vdev.get_config = virtio_scsi_get_config;
+    s->vdev.get_features = virtio_scsi_get_features;
+
+    s->event_info_size = sizeof(VirtIOSCSIEvent);
+    s->sense_size = VIRTIO_SCSI_SENSE_SIZE;
+    s->cdb_size = VIRTIO_SCSI_CDB_SIZE;
+
+    s->ctrl_vq = virtio_add_queue(&s->vdev, VIRTIO_SCSI_VQ_SIZE,
+                                   virtio_scsi_handle_ctrl);
+    s->event_vq = virtio_add_queue(&s->vdev, VIRTIO_SCSI_VQ_SIZE,
+                                   NULL);
+    s->cmd_vq = virtio_add_queue(&s->vdev, VIRTIO_SCSI_VQ_SIZE,
+                                   virtio_scsi_handle_cmd);
+
+    /* TODO savevm */
+    /* TODO boot device path */
+
+    return &s->vdev;
+}
+
+void virtio_scsi_exit(VirtIODevice *vdev)
+{
+    virtio_cleanup(vdev);
+}
diff --git a/hw/virtio-scsi.h b/hw/virtio-scsi.h
new file mode 100644
index 0000000..fcf8967
--- /dev/null
+++ b/hw/virtio-scsi.h
@@ -0,0 +1,28 @@
+/*
+ * Virtio SCSI HBA
+ *
+ * Copyright IBM, Corp. 2010
+ *
+ * Authors:
+ *  Stefan Hajnoczi    <stefanha@linux.vnet.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef _QEMU_VIRTIO_SCSI_H
+#define _QEMU_VIRTIO_SCSI_H
+
+#include "virtio.h"
+#include "net.h"
+#include "pci.h"
+
+/* The ID for virtio_scsi */
+#define VIRTIO_ID_SCSI  6
+
+struct VirtIOSCSIConf {
+    uint32_t num_queues;
+};
+
+#endif /* _QEMU_VIRTIO_SCSI_H */
diff --git a/hw/virtio.h b/hw/virtio.h
index 2d18209..91daa32 100644
--- a/hw/virtio.h
+++ b/hw/virtio.h
@@ -198,6 +198,8 @@ VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf,
 typedef struct virtio_serial_conf virtio_serial_conf;
 VirtIODevice *virtio_serial_init(DeviceState *dev, virtio_serial_conf *serial);
 VirtIODevice *virtio_balloon_init(DeviceState *dev);
+typedef struct VirtIOSCSIConf VirtIOSCSIConf;
+VirtIODevice *virtio_scsi_init(DeviceState *dev, VirtIOSCSIConf *conf);
 #ifdef CONFIG_LINUX
 VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf);
 #endif
@@ -207,6 +209,7 @@ void virtio_net_exit(VirtIODevice *vdev);
 void virtio_blk_exit(VirtIODevice *vdev);
 void virtio_serial_exit(VirtIODevice *vdev);
 void virtio_balloon_exit(VirtIODevice *vdev);
+void virtio_scsi_exit(VirtIODevice *vdev);
 
 #define DEFINE_VIRTIO_COMMON_FEATURES(_state, _field) \
 	DEFINE_PROP_BIT("indirect_desc", _state, _field, \
-- 
1.7.7.1

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [Qemu-devel] [PATCH 2/4] virtio-scsi: Add basic request processing infrastructure
  2011-11-15 17:00 [Qemu-devel] [RFC PATCH 0/4] virtio-scsi device model Paolo Bonzini
  2011-11-15 17:00 ` [Qemu-devel] [PATCH 1/4] virtio-scsi: Add virtio-scsi stub device Paolo Bonzini
@ 2011-11-15 17:00 ` Paolo Bonzini
  2011-11-16  8:28   ` Zhi Yong Wu
  2011-11-15 17:00 ` [Qemu-devel] [PATCH 3/4] virtio-scsi: add basic SCSI bus operation Paolo Bonzini
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 9+ messages in thread
From: Paolo Bonzini @ 2011-11-15 17:00 UTC (permalink / raw)
  To: qemu-devel; +Cc: stefanha, mst

From: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>

Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 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);
+}
+
+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

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [Qemu-devel] [PATCH 3/4] virtio-scsi: add basic SCSI bus operation
  2011-11-15 17:00 [Qemu-devel] [RFC PATCH 0/4] virtio-scsi device model Paolo Bonzini
  2011-11-15 17:00 ` [Qemu-devel] [PATCH 1/4] virtio-scsi: Add virtio-scsi stub device Paolo Bonzini
  2011-11-15 17:00 ` [Qemu-devel] [PATCH 2/4] virtio-scsi: Add basic request processing infrastructure Paolo Bonzini
@ 2011-11-15 17:00 ` Paolo Bonzini
  2011-11-15 17:00 ` [Qemu-devel] [PATCH 4/4] virtio-scsi: process control queue requests Paolo Bonzini
  2011-11-15 20:33 ` [Qemu-devel] [RFC PATCH 0/4] virtio-scsi device model Michael S. Tsirkin
  4 siblings, 0 replies; 9+ messages in thread
From: Paolo Bonzini @ 2011-11-15 17:00 UTC (permalink / raw)
  To: qemu-devel; +Cc: stefanha, mst

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/virtio-scsi.c |   99 ++++++++++++++++++++++++++++++++++++++++++++++++------
 1 files changed, 88 insertions(+), 11 deletions(-)

diff --git a/hw/virtio-scsi.c b/hw/virtio-scsi.c
index 7e6348a..5fc3c00 100644
--- a/hw/virtio-scsi.c
+++ b/hw/virtio-scsi.c
@@ -119,6 +119,7 @@ typedef struct {
     DeviceState *qdev;
     VirtIOSCSIConf *conf;
 
+    SCSIBus bus;
     VirtQueue *ctrl_vq;
     VirtQueue *event_vq;
     VirtQueue *cmd_vq;
@@ -149,6 +150,22 @@ typedef struct VirtIOSCSIReq {
     } resp;
 } VirtIOSCSIReq;
 
+static inline int virtio_scsi_get_lun(uint8_t *lun)
+{
+    return ((lun[2] << 8) | lun[3]) & 0x3FFF;
+}
+
+static inline SCSIDevice *virtio_scsi_device_find(VirtIOSCSI *s, uint8_t *lun)
+{
+    if (lun[0] != 1) {
+        return NULL;
+    }
+    if (lun[2] != 0 && !(lun[2] >= 0x40 && lun[2] < 0x7F)) {
+        return NULL;
+    }
+    return scsi_device_find(&s->bus, 0, lun[1], virtio_scsi_get_lun(lun));
+}
+
 static void virtio_scsi_complete_req(VirtIOSCSIReq *req)
 {
     VirtQueue *vq = req->vq;
@@ -228,6 +245,36 @@ static void virtio_scsi_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
     }
 }
 
+static void virtio_scsi_command_complete(SCSIRequest *r, uint32_t status,
+                                         int32_t resid)
+{
+    VirtIOSCSIReq *req = r->hba_private;
+
+    req->resp.cmd->response = VIRTIO_SCSI_S_OK;
+    req->resp.cmd->status = status;
+    if (req->resp.cmd->status == GOOD) {
+        req->resp.cmd->resid = resid;
+        if (resid) {
+            req->resp.cmd->response = VIRTIO_SCSI_S_UNDERRUN;
+        }
+    } else {
+       req->resp.cmd->resid = 0;
+       scsi_req_get_sense(r, req->resp.cmd->sense, VIRTIO_SCSI_SENSE_SIZE);
+    }
+    virtio_scsi_complete_req(req);
+}
+
+static void virtio_scsi_request_cancelled(SCSIRequest *r)
+{
+    VirtIOSCSIReq *req = r->hba_private;
+
+    if (!req) {
+        return;
+    }
+    req->resp.cmd->response = VIRTIO_SCSI_S_ABORTED;
+    virtio_scsi_complete_req(req);
+}
+
 static void virtio_scsi_fail_cmd_req(VirtIOSCSI *s, VirtIOSCSIReq *req)
 {
     req->resp.cmd->response = VIRTIO_SCSI_S_FAILURE;
@@ -238,8 +285,10 @@ static void virtio_scsi_handle_cmd(VirtIODevice *vdev, VirtQueue *vq)
 {
     VirtIOSCSI *s = (VirtIOSCSI *)vdev;
     VirtIOSCSIReq *req;
+    int n;
 
     while ((req = virtio_scsi_parse_req(s, vq))) {
+        SCSIDevice *d;
         int out_size, in_size;
         if (req->elem.out_num < 1 || req->elem.in_num < 1) {
             virtio_scsi_bad_req();
@@ -257,17 +306,31 @@ static void virtio_scsi_handle_cmd(VirtIODevice *vdev, VirtQueue *vq)
             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);
+        d = virtio_scsi_device_find(s, req->req.cmd->lun);
+        if (!d) {
+            req->resp.cmd->response = VIRTIO_SCSI_S_BAD_TARGET;
+            virtio_scsi_complete_req(req);
+            continue;
+        }
+        req->sreq = scsi_req_new(d, req->req.cmd->tag,
+                                 virtio_scsi_get_lun(req->req.cmd->lun),
+                                 req->req.cmd->cdb, req);
+
+        if (req->sreq->cmd.mode != SCSI_XFER_NONE) {
+            int req_mode =
+                (req->elem.in_num > 1 ? SCSI_XFER_FROM_DEV : SCSI_XFER_TO_DEV);
+
+            if (req->sreq->cmd.mode != req_mode) {
+                virtio_scsi_fail_cmd_req(s, req);
+                scsi_req_cancel(req->sreq);
+                continue;
+            }
+        }
+
+        n = scsi_req_enqueue(req->sreq, &req->qsgl);
+        if (n) {
+            scsi_req_continue(req->sreq);
+        }
     }
 }
 
@@ -290,6 +353,15 @@ static uint32_t virtio_scsi_get_features(VirtIODevice *vdev,
     return requested_features;
 }
 
+static struct SCSIBusInfo virtio_scsi_scsi_info = {
+    .tcq = true,
+    .max_target = 255,
+    .max_lun = 16383,
+
+    .complete = virtio_scsi_command_complete,
+    .cancel = virtio_scsi_request_cancelled,
+};
+
 VirtIODevice *virtio_scsi_init(DeviceState *dev, VirtIOSCSIConf *proxyconf)
 {
     VirtIOSCSI *s;
@@ -316,6 +388,11 @@ VirtIODevice *virtio_scsi_init(DeviceState *dev, VirtIOSCSIConf *proxyconf)
     s->cmd_vq = virtio_add_queue(&s->vdev, VIRTIO_SCSI_VQ_SIZE,
                                    virtio_scsi_handle_cmd);
 
+    scsi_bus_new(&s->bus, dev, &virtio_scsi_scsi_info);
+    if (!dev->hotplugged) {
+        scsi_bus_legacy_handle_cmdline(&s->bus);
+    }
+
     /* TODO savevm */
     /* TODO boot device path */
 
-- 
1.7.7.1

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [Qemu-devel] [PATCH 4/4] virtio-scsi: process control queue requests
  2011-11-15 17:00 [Qemu-devel] [RFC PATCH 0/4] virtio-scsi device model Paolo Bonzini
                   ` (2 preceding siblings ...)
  2011-11-15 17:00 ` [Qemu-devel] [PATCH 3/4] virtio-scsi: add basic SCSI bus operation Paolo Bonzini
@ 2011-11-15 17:00 ` Paolo Bonzini
  2011-11-15 20:33 ` [Qemu-devel] [RFC PATCH 0/4] virtio-scsi device model Michael S. Tsirkin
  4 siblings, 0 replies; 9+ messages in thread
From: Paolo Bonzini @ 2011-11-15 17:00 UTC (permalink / raw)
  To: qemu-devel; +Cc: stefanha, mst

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/virtio-scsi.c |  111 ++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 104 insertions(+), 7 deletions(-)

diff --git a/hw/virtio-scsi.c b/hw/virtio-scsi.c
index 5fc3c00..146ea6e 100644
--- a/hw/virtio-scsi.c
+++ b/hw/virtio-scsi.c
@@ -224,15 +224,88 @@ static VirtIOSCSIReq *virtio_scsi_parse_req(VirtIOSCSI *s, VirtQueue *vq)
     return req;
 }
 
-static void virtio_scsi_fail_ctrl_req(VirtIOSCSI *s, VirtIOSCSIReq *req)
+static void virtio_scsi_do_tmf(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;
+    SCSIDevice *d = virtio_scsi_device_find(s, req->req.cmd->lun);
+    SCSIRequest *r, *next;
+    DeviceState *qdev;
+    int target;
+
+    switch (req->req.tmf->subtype) {
+    case VIRTIO_SCSI_T_TMF_ABORT_TASK:
+    case VIRTIO_SCSI_T_TMF_QUERY_TASK:
+        d = virtio_scsi_device_find(s, req->req.cmd->lun);
+        if (!d) {
+            goto fail;
+        }
+
+        QTAILQ_FOREACH_SAFE(r, &d->requests, next, next) {
+            if (r->tag == req->req.cmd->tag) {
+                break;
+            }
+        }
+        if (r && r->hba_private) {
+            if (req->req.tmf->subtype == VIRTIO_SCSI_T_TMF_ABORT_TASK) {
+                scsi_req_cancel(r);
+            }
+            req->resp.tmf->response = VIRTIO_SCSI_S_FUNCTION_SUCCEEDED;
+        } else {
+            req->resp.tmf->response = VIRTIO_SCSI_S_OK;
+        }
+        break;
+
+    case VIRTIO_SCSI_T_TMF_LOGICAL_UNIT_RESET:
+        d = virtio_scsi_device_find(s, req->req.cmd->lun);
+        if (!d) {
+            goto fail;
+        }
+        if (d->lun == virtio_scsi_get_lun(req->req.cmd->lun)) {
+            qdev_reset_all(&d->qdev);
+        }
+        break;
+
+    case VIRTIO_SCSI_T_TMF_ABORT_TASK_SET:
+    case VIRTIO_SCSI_T_TMF_CLEAR_TASK_SET:
+    case VIRTIO_SCSI_T_TMF_QUERY_TASK_SET:
+        d = virtio_scsi_device_find(s, req->req.cmd->lun);
+        if (!d) {
+            goto fail;
+        }
+        if (d->lun != virtio_scsi_get_lun(req->req.cmd->lun)) {
+            req->resp.tmf->response = VIRTIO_SCSI_S_OK;
+            break;
+        }
+        req->resp.tmf->response = VIRTIO_SCSI_S_OK;
+        QTAILQ_FOREACH_SAFE(r, &d->requests, next, next) {
+            if (r->hba_private) {
+                if (req->req.tmf->subtype == VIRTIO_SCSI_T_TMF_ABORT_TASK) {
+                    scsi_req_cancel(r);
+                }
+                req->resp.tmf->response = VIRTIO_SCSI_S_FUNCTION_SUCCEEDED;
+            }
+        }
+        break;
+
+    case VIRTIO_SCSI_T_TMF_I_T_NEXUS_RESET:
+        target = req->req.cmd->lun[1];
+        QTAILQ_FOREACH(qdev, &s->bus.qbus.children, sibling) {
+             d = DO_UPCAST(SCSIDevice, qdev, qdev);
+             if (d->channel == 0 && d->id == target) {
+                qdev_reset_all(&d->qdev);
+             }
+        }
+        break;
+
+    case VIRTIO_SCSI_T_TMF_CLEAR_ACA:
+    default:
+        req->resp.tmf->response = VIRTIO_SCSI_S_FUNCTION_REJECTED;
+        break;
     }
 
-    virtio_scsi_complete_req(req);
+    return;
+
+fail:
+    req->resp.tmf->response = VIRTIO_SCSI_S_BAD_TARGET;
 }
 
 static void virtio_scsi_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
@@ -241,7 +314,31 @@ static void virtio_scsi_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
     VirtIOSCSIReq *req;
 
     while ((req = virtio_scsi_parse_req(s, vq))) {
-        virtio_scsi_fail_ctrl_req(s, req);
+        int out_size, in_size;
+        if (req->elem.out_num < 1 || req->elem.in_num < 1) {
+            virtio_scsi_bad_req();
+            continue;
+        }
+
+        out_size = req->elem.out_sg[0].iov_len;
+        in_size = req->elem.in_sg[0].iov_len;
+        if (req->req.tmf->type == VIRTIO_SCSI_T_TMF) {
+            if (out_size < sizeof(VirtIOSCSICtrlTMFReq) ||
+                in_size < sizeof(VirtIOSCSICtrlTMFResp)) {
+                virtio_scsi_bad_req();
+            }
+            virtio_scsi_do_tmf(s, req);
+
+        } else if (req->req.tmf->type == VIRTIO_SCSI_T_AN_QUERY ||
+                   req->req.tmf->type == VIRTIO_SCSI_T_AN_SUBSCRIBE) {
+            if (out_size < sizeof(VirtIOSCSICtrlANReq) ||
+                in_size < sizeof(VirtIOSCSICtrlANResp)) {
+                virtio_scsi_bad_req();
+            }
+            req->resp.an->event_actual = 0;
+            req->resp.an->response = VIRTIO_SCSI_S_OK;
+        }
+        virtio_scsi_complete_req(req);
     }
 }
 
-- 
1.7.7.1

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [Qemu-devel] [RFC PATCH 0/4] virtio-scsi device model
  2011-11-15 17:00 [Qemu-devel] [RFC PATCH 0/4] virtio-scsi device model Paolo Bonzini
                   ` (3 preceding siblings ...)
  2011-11-15 17:00 ` [Qemu-devel] [PATCH 4/4] virtio-scsi: process control queue requests Paolo Bonzini
@ 2011-11-15 20:33 ` Michael S. Tsirkin
  2011-11-16  7:51   ` Paolo Bonzini
  4 siblings, 1 reply; 9+ messages in thread
From: Michael S. Tsirkin @ 2011-11-15 20:33 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-devel, stefanha

On Tue, Nov 15, 2011 at 06:00:01PM +0100, Paolo Bonzini wrote:
> Here is the first sneak peek of virtio-scsi.  It's on top of my scsi-sg
> branch at http://github.com/bonzini/qemu.  I'm more interested
> in getting early reviews in the virtio side, so I'm omitting the
> scsi-specific patches that introduce support for scatter/gather I/O
> in the SCSI layer.
> 
> What's missing is 1) support for writable config space, 2) testing TMF,
> 3) events; 4) migration.  The last two do not need to be in at the
> first commit, they can come later.
> 
> Tested lightly with a seabios driver (see the seabios ML).  The Linux
> driver will come next...

spec patches?

> Paolo Bonzini (2):
>   virtio-scsi: add basic SCSI bus operation
>   virtio-scsi: process control queue requests
> 
> Stefan Hajnoczi (2):
>   virtio-scsi: Add virtio-scsi stub device
>   virtio-scsi: Add basic request processing infrastructure
> 
>  Makefile.target         |    1 +
>  default-configs/pci.mak |    1 +
>  hw/pci.h                |    1 +
>  hw/virtio-pci.c         |   42 ++++
>  hw/virtio-pci.h         |    2 +
>  hw/virtio-scsi.c        |  502 +++++++++++++++++++++++++++++++++++++++++++++++
>  hw/virtio-scsi.h        |   28 +++
>  hw/virtio.h             |    3 +
>  8 files changed, 580 insertions(+), 0 deletions(-)
>  create mode 100644 hw/virtio-scsi.c
>  create mode 100644 hw/virtio-scsi.h
> 
> -- 
> 1.7.7.1

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [Qemu-devel] [RFC PATCH 0/4] virtio-scsi device model
  2011-11-15 20:33 ` [Qemu-devel] [RFC PATCH 0/4] virtio-scsi device model Michael S. Tsirkin
@ 2011-11-16  7:51   ` Paolo Bonzini
  0 siblings, 0 replies; 9+ messages in thread
From: Paolo Bonzini @ 2011-11-16  7:51 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: qemu-devel, stefanha

On 11/15/2011 09:33 PM, Michael S. Tsirkin wrote:
> >  What's missing is 1) support for writable config space, 2) testing TMF,
> >  3) events; 4) migration.  The last two do not need to be in at the
> >  first commit, they can come later.
> >
> >  Tested lightly with a seabios driver (see the seabios ML).  The Linux
> >  driver will come next...
>
> spec patches?

The txt version is at 
http://lists.gnu.org/archive/html/qemu-devel/2011-10/txtXx0CcI94xv.txt

The LyX version will come soon, the changes from v3 are quite small so 
now that we have an implementation it can go in.

Paolo

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [Qemu-devel] [PATCH 2/4] virtio-scsi: Add basic request processing infrastructure
  2011-11-15 17:00 ` [Qemu-devel] [PATCH 2/4] virtio-scsi: Add basic request processing infrastructure Paolo Bonzini
@ 2011-11-16  8:28   ` Zhi Yong Wu
  2011-11-16  8:29     ` Paolo Bonzini
  0 siblings, 1 reply; 9+ messages in thread
From: Zhi Yong Wu @ 2011-11-16  8:28 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: mst, qemu-devel, stefanha

On Wed, Nov 16, 2011 at 1:00 AM, Paolo Bonzini <pbonzini@redhat.com> wrote:
> From: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
>
> Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
>  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

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [Qemu-devel] [PATCH 2/4] virtio-scsi: Add basic request processing infrastructure
  2011-11-16  8:28   ` Zhi Yong Wu
@ 2011-11-16  8:29     ` Paolo Bonzini
  0 siblings, 0 replies; 9+ messages in thread
From: Paolo Bonzini @ 2011-11-16  8:29 UTC (permalink / raw)
  To: Zhi Yong Wu; +Cc: mst, qemu-devel, stefanha

On 11/16/2011 09:28 AM, Zhi Yong Wu wrote:
>> >  +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?

Yes, thanks for spotting it.

Paolo

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2011-11-16  8:29 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-11-15 17:00 [Qemu-devel] [RFC PATCH 0/4] virtio-scsi device model Paolo Bonzini
2011-11-15 17:00 ` [Qemu-devel] [PATCH 1/4] virtio-scsi: Add virtio-scsi stub device Paolo Bonzini
2011-11-15 17:00 ` [Qemu-devel] [PATCH 2/4] virtio-scsi: Add basic request processing infrastructure Paolo Bonzini
2011-11-16  8:28   ` Zhi Yong Wu
2011-11-16  8:29     ` Paolo Bonzini
2011-11-15 17:00 ` [Qemu-devel] [PATCH 3/4] virtio-scsi: add basic SCSI bus operation Paolo Bonzini
2011-11-15 17:00 ` [Qemu-devel] [PATCH 4/4] virtio-scsi: process control queue requests Paolo Bonzini
2011-11-15 20:33 ` [Qemu-devel] [RFC PATCH 0/4] virtio-scsi device model Michael S. Tsirkin
2011-11-16  7:51   ` Paolo Bonzini

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).