[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH] scsi-bus: fix to allow some special SCSI commands
From: |
TAMUKI Shoichi |
Subject: |
[Qemu-devel] [PATCH] scsi-bus: fix to allow some special SCSI commands |
Date: |
Fri, 11 Jul 2014 17:53:31 +0900 |
Currently, some special SCSI commands sent from the initiator in a
guest do not reach the target device. To avoid this, extended (0x7e,)
variable length (0x7f,) and vendor specific (0xc0..0xff) opcodes are
now treated as valid CDBs.
Originally, the most significant 3 bits of a SCSI opcode specified the
length of the CDB. However, when variable-length CDBs were created,
this correspondence was changed, and the entire opcode must be
examined to determine the CDB length. The CDBs with the opcodes above
are done that way for now.
Signed-off-by: TAMUKI Shoichi <address@hidden>
---
hw/scsi/scsi-bus.c | 21 ++++++++++++++++++---
hw/scsi/virtio-scsi.c | 25 -------------------------
include/hw/virtio/virtio-scsi.h | 25 +++++++++++++++++++++++++
3 files changed, 43 insertions(+), 28 deletions(-)
diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c
index ea1ac09..c631ebd 100644
--- a/hw/scsi/scsi-bus.c
+++ b/hw/scsi/scsi-bus.c
@@ -6,10 +6,12 @@
#include "sysemu/blockdev.h"
#include "trace.h"
#include "sysemu/dma.h"
+#include "hw/virtio/virtio-scsi.h"
static char *scsibus_get_dev_path(DeviceState *dev);
static char *scsibus_get_fw_dev_path(DeviceState *dev);
-static int scsi_req_parse(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf);
+static int scsi_req_parse(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf,
+ uint32_t len);
static void scsi_req_dequeue(SCSIRequest *req);
static uint8_t *scsi_target_alloc_buf(SCSIRequest *req, size_t len);
static void scsi_target_free_buf(SCSIRequest *req);
@@ -563,7 +565,8 @@ SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag,
uint32_t lun,
SCSIRequest *req;
SCSICommand cmd;
- if (scsi_req_parse(&cmd, d, buf) != 0) {
+ if (scsi_req_parse(&cmd, d, buf,
+ ((VirtIOSCSIReq *) hba_private)->dev->parent_obj.cdb_size) != 0) {
trace_scsi_req_parse_bad(d->id, lun, tag, buf[0]);
req = scsi_req_alloc(&reqops_invalid_opcode, d, tag, lun, hba_private);
} else {
@@ -1181,7 +1184,8 @@ static uint64_t scsi_cmd_lba(SCSICommand *cmd)
return lba;
}
-static int scsi_req_parse(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
+static int scsi_req_parse(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf,
+ uint32_t len)
{
int rc;
@@ -1193,12 +1197,23 @@ static int scsi_req_parse(SCSICommand *cmd, SCSIDevice
*dev, uint8_t *buf)
case 2:
cmd->len = 10;
break;
+ case 3:
+ if (buf[0] == 0x7e || (buf[0] == 0x7f && len >= 16)) {
+ cmd->len = len;
+ } else {
+ return -1;
+ }
+ break;
case 4:
cmd->len = 16;
break;
case 5:
cmd->len = 12;
break;
+ case 6:
+ case 7:
+ cmd->len = len;
+ break;
default:
return -1;
}
diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
index 0eb069a..c5710aa 100644
--- a/hw/scsi/virtio-scsi.c
+++ b/hw/scsi/virtio-scsi.c
@@ -21,31 +21,6 @@
#include <hw/virtio/virtio-bus.h>
#include "hw/virtio/virtio-access.h"
-typedef struct VirtIOSCSIReq {
- VirtIOSCSI *dev;
- VirtQueue *vq;
- VirtQueueElement elem;
- QEMUSGList qsgl;
- SCSIRequest *sreq;
- size_t resp_size;
- enum SCSIXferMode mode;
- QEMUIOVector resp_iov;
- union {
- VirtIOSCSICmdResp cmd;
- VirtIOSCSICtrlTMFResp tmf;
- VirtIOSCSICtrlANResp an;
- VirtIOSCSIEvent event;
- } resp;
- union {
- struct {
- VirtIOSCSICmdReq cmd;
- uint8_t cdb[];
- } QEMU_PACKED;
- VirtIOSCSICtrlTMFReq tmf;
- VirtIOSCSICtrlANReq an;
- } req;
-} VirtIOSCSIReq;
-
QEMU_BUILD_BUG_ON(offsetof(VirtIOSCSIReq, req.cdb) !=
offsetof(VirtIOSCSIReq, req.cmd) + sizeof(VirtIOSCSICmdReq));
diff --git a/include/hw/virtio/virtio-scsi.h b/include/hw/virtio/virtio-scsi.h
index 0419ee4..fae3f81 100644
--- a/include/hw/virtio/virtio-scsi.h
+++ b/include/hw/virtio/virtio-scsi.h
@@ -172,6 +172,31 @@ typedef struct {
bool events_dropped;
} VirtIOSCSI;
+typedef struct VirtIOSCSIReq {
+ VirtIOSCSI *dev;
+ VirtQueue *vq;
+ VirtQueueElement elem;
+ QEMUSGList qsgl;
+ SCSIRequest *sreq;
+ size_t resp_size;
+ enum SCSIXferMode mode;
+ QEMUIOVector resp_iov;
+ union {
+ VirtIOSCSICmdResp cmd;
+ VirtIOSCSICtrlTMFResp tmf;
+ VirtIOSCSICtrlANResp an;
+ VirtIOSCSIEvent event;
+ } resp;
+ union {
+ struct {
+ VirtIOSCSICmdReq cmd;
+ uint8_t cdb[];
+ } QEMU_PACKED;
+ VirtIOSCSICtrlTMFReq tmf;
+ VirtIOSCSICtrlANReq an;
+ } req;
+} VirtIOSCSIReq;
+
#define DEFINE_VIRTIO_SCSI_PROPERTIES(_state, _conf_field)
\
DEFINE_PROP_UINT32("num_queues", _state, _conf_field.num_queues, 1),
\
DEFINE_PROP_UINT32("max_sectors", _state, _conf_field.max_sectors,
0xFFFF),\
--
1.9.0
- [Qemu-devel] [PATCH] scsi-bus: fix to allow some special SCSI commands,
TAMUKI Shoichi <=