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