Patchwork [5/5] scsi: Ensure command and transfer lengths are set for all SCSI stream commands.

login
register
mail settings
Submitter Paolo Bonzini
Date June 14, 2012, 2:21 p.m.
Message ID <4FD9F378.5050703@redhat.com>
Download mbox | patch
Permalink /patch/164939/
State New
Headers show

Comments

Paolo Bonzini - June 14, 2012, 2:21 p.m.
Il 14/06/2012 15:55, Christian Borntraeger ha scritto:
> From: Christian Hoff <christian.hoff@de.ibm.com>
> 
> scsi-generic relies on those values to be correct, so it is important that
> those values are initialized properly prior to submitting the SCSI command.

This and the similar code in patch 3/5 can be replaced by the attached
patch.  You can test the result at git://github.com/bonzini/qemu.git
branch scsi-devel.

Paolo

Patch

From 387da72123720635aeb27b3b67ee3f060b926f3b Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Thu, 14 Jun 2012 16:13:49 +0200
Subject: [PATCH] scsi: Ensure command and transfer lengths are set for all
 SCSI devices

scsi-generic relies on those values to be correct, so it is important that
those values are initialized properly for all device types.

Reported-by: Christian Hoff <christian.hoff@de.ibm.com>
Reported-by: Christian Borntraeger <borntraeger@de.ibm.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/scsi-bus.c |   25 ++++++++++++++++++-------
 1 file changed, 18 insertions(+), 7 deletions(-)

diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index 99e37b5..7ad6538 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -723,20 +723,16 @@  static int scsi_req_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
     switch (buf[0] >> 5) {
     case 0:
         cmd->xfer = buf[4];
-        cmd->len = 6;
         break;
     case 1:
     case 2:
         cmd->xfer = lduw_be_p(&buf[7]);
-        cmd->len = 10;
         break;
     case 4:
         cmd->xfer = ldl_be_p(&buf[10]) & 0xffffffffULL;
-        cmd->len = 16;
         break;
     case 5:
         cmd->xfer = ldl_be_p(&buf[6]) & 0xffffffffULL;
-        cmd->len = 12;
         break;
     default:
         return -1;
@@ -873,7 +869,6 @@  static int scsi_req_stream_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *bu
     case READ_REVERSE:
     case RECOVER_BUFFERED_DATA:
     case WRITE_6:
-        cmd->len = 6;
         cmd->xfer = buf[4] | (buf[3] << 8) | (buf[2] << 16);
         if (buf[1] & 0x01) { /* fixed */
             cmd->xfer *= dev->blocksize;
@@ -883,7 +878,6 @@  static int scsi_req_stream_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *bu
     case READ_REVERSE_16:
     case VERIFY_16:
     case WRITE_16:
-        cmd->len = 16;
         cmd->xfer = buf[14] | (buf[13] << 8) | (buf[12] << 16);
         if (buf[1] & 0x01) { /* fixed */
             cmd->xfer *= dev->blocksize;
@@ -891,7 +885,6 @@  static int scsi_req_stream_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *bu
         break;
     case REWIND:
     case LOAD_UNLOAD:
-        cmd->len = 6;
         cmd->xfer = 0;
         break;
     case SPACE_16:
@@ -989,6 +982,24 @@  int scsi_req_parse(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
 {
     int rc;
 
+    switch (buf[0] >> 5) {
+    case 0:
+        cmd->len = 6;
+        break;
+    case 1:
+    case 2:
+        cmd->len = 10;
+        break;
+    case 4:
+        cmd->len = 16;
+        break;
+    case 5:
+        cmd->len = 12;
+        break;
+    default:
+        return -1;
+    }
+
     if (dev->type == TYPE_TAPE) {
         rc = scsi_req_stream_length(cmd, dev, buf);
     } else {
-- 
1.7.10.2