* [Qemu-devel] [PATCH] scsi-bus: fix to allow some special SCSI commands
@ 2014-07-11 8:53 TAMUKI Shoichi
2014-07-11 9:02 ` Paolo Bonzini
0 siblings, 1 reply; 3+ messages in thread
From: TAMUKI Shoichi @ 2014-07-11 8:53 UTC (permalink / raw)
To: qemu-devel; +Cc: pbonzini, tamuki
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 <tamuki@linet.gr.jp>
---
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
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [Qemu-devel] [PATCH] scsi-bus: fix to allow some special SCSI commands
2014-07-11 8:53 [Qemu-devel] [PATCH] scsi-bus: fix to allow some special SCSI commands TAMUKI Shoichi
@ 2014-07-11 9:02 ` Paolo Bonzini
2014-07-12 10:21 ` TAMUKI Shoichi
0 siblings, 1 reply; 3+ messages in thread
From: Paolo Bonzini @ 2014-07-11 9:02 UTC (permalink / raw)
To: TAMUKI Shoichi, qemu-devel
Il 11/07/2014 10:53, TAMUKI Shoichi ha scritto:
> @@ -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 {
This function is not called only for virtio-scsi. You need to add a new
argument to scsi_req_new, and modify all invocations in hw/scsi.
Thanks,
Paolo
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [Qemu-devel] [PATCH] scsi-bus: fix to allow some special SCSI commands
2014-07-11 9:02 ` Paolo Bonzini
@ 2014-07-12 10:21 ` TAMUKI Shoichi
0 siblings, 0 replies; 3+ messages in thread
From: TAMUKI Shoichi @ 2014-07-12 10:21 UTC (permalink / raw)
To: qemu-devel; +Cc: Paolo Bonzini, TAMUKI Shoichi
Hello,
From: Paolo Bonzini <pbonzini@redhat.com>
Subject: Re: [PATCH] scsi-bus: fix to allow some special SCSI commands
Date: Fri, 11 Jul 2014 11:02:41 +0200
> > @@ -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 {
>
> This function is not called only for virtio-scsi. You need to add a new
> argument to scsi_req_new, and modify all invocations in hw/scsi.
Thank you for your quick response. It is just as you say.
I will send the revised patch soon.
Regards,
TAMUKI Shoichi
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2014-07-12 10:21 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-07-11 8:53 [Qemu-devel] [PATCH] scsi-bus: fix to allow some special SCSI commands TAMUKI Shoichi
2014-07-11 9:02 ` Paolo Bonzini
2014-07-12 10:21 ` TAMUKI Shoichi
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).