Patchwork [03/16] scsi: pass status when completing

login
register
mail settings
Submitter Paolo Bonzini
Date Aug. 3, 2011, 8:49 a.m.
Message ID <1312361359-15445-4-git-send-email-pbonzini@redhat.com>
Download mbox | patch
Permalink /patch/108055/
State New
Headers show

Comments

Paolo Bonzini - Aug. 3, 2011, 8:49 a.m.
A small improvement in the SCSI request API.  Pass the status
at the time the request is completed, so that we can assert that
no request is completed twice.  This would have detected the
problem fixed in the previous patch.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/scsi-bus.c     |    8 ++++----
 hw/scsi-disk.c    |   15 ++++-----------
 hw/scsi-generic.c |   31 ++++++++++++++++---------------
 hw/scsi.h         |    2 +-
 4 files changed, 25 insertions(+), 31 deletions(-)
Christoph Hellwig - Aug. 3, 2011, 4:34 p.m.
On Wed, Aug 03, 2011 at 10:49:06AM +0200, Paolo Bonzini wrote:
> A small improvement in the SCSI request API.  Pass the status
> at the time the request is completed, so that we can assert that
> no request is completed twice.  This would have detected the
> problem fixed in the previous patch.
> 
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

Looks good,

Reviewed-by: Christoph Hellwig <hch@lst.de>

Patch

diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index 8b1a412..bff2f5b 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -672,9 +672,10 @@  void scsi_req_print(SCSIRequest *req)
     }
 }
 
-void scsi_req_complete(SCSIRequest *req)
+void scsi_req_complete(SCSIRequest *req, int status)
 {
-    assert(req->status != -1);
+    assert(req->status == -1);
+    req->status = status;
     scsi_req_ref(req);
     scsi_req_dequeue(req);
     req->bus->ops->complete(req, req->status);
@@ -696,11 +697,10 @@  void scsi_req_cancel(SCSIRequest *req)
 
 void scsi_req_abort(SCSIRequest *req, int status)
 {
-    req->status = status;
     if (req->dev && req->dev->info->cancel_io) {
         req->dev->info->cancel_io(req);
     }
-    scsi_req_complete(req);
+    scsi_req_complete(req, status);
 }
 
 void scsi_device_purge_requests(SCSIDevice *sdev)
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 814bf74..8beaebf 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -105,21 +105,15 @@  static void scsi_disk_clear_sense(SCSIDiskState *s)
     memset(&s->sense, 0, sizeof(s->sense));
 }
 
-static void scsi_req_set_status(SCSIDiskReq *r, int status, SCSISense sense)
-{
-    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
-
-    r->req.status = status;
-    s->sense = sense;
-}
-
 /* Helper function for command completion.  */
 static void scsi_command_complete(SCSIDiskReq *r, int status, SCSISense sense)
 {
+    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
+
     DPRINTF("Command complete tag=0x%x status=%d sense=%d/%d/%d\n",
             r->req.tag, status, sense.key, sense.asc, sense.ascq);
-    scsi_req_set_status(r, status, sense);
-    scsi_req_complete(&r->req);
+    s->sense = sense;
+    scsi_req_complete(&r->req, status);
 }
 
 /* Cancel a pending data transfer.  */
@@ -979,7 +973,6 @@  static int scsi_disk_emulate_command(SCSIDiskReq *r, uint8_t *outbuf)
         scsi_command_complete(r, CHECK_CONDITION, SENSE_CODE(INVALID_OPCODE));
         return -1;
     }
-    scsi_req_set_status(r, GOOD, SENSE_CODE(NO_SENSE));
     return buflen;
 
 not_ready:
diff --git a/hw/scsi-generic.c b/hw/scsi-generic.c
index 63361b3..f119f33 100644
--- a/hw/scsi-generic.c
+++ b/hw/scsi-generic.c
@@ -115,6 +115,7 @@  static void scsi_free_request(SCSIRequest *req)
 /* Helper function for command completion.  */
 static void scsi_command_complete(void *opaque, int ret)
 {
+    int status;
     SCSIGenericReq *r = (SCSIGenericReq *)opaque;
     SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, r->req.dev);
 
@@ -126,36 +127,37 @@  static void scsi_command_complete(void *opaque, int ret)
     if (ret != 0) {
         switch (ret) {
         case -EDOM:
-            r->req.status = TASK_SET_FULL;
+            status = TASK_SET_FULL;
             break;
         case -EINVAL:
-            r->req.status = CHECK_CONDITION;
+            status = CHECK_CONDITION;
             scsi_set_sense(s, SENSE_CODE(INVALID_FIELD));
             break;
         case -ENOMEM:
-            r->req.status = CHECK_CONDITION;
+            status = CHECK_CONDITION;
             scsi_set_sense(s, SENSE_CODE(TARGET_FAILURE));
             break;
         default:
-            r->req.status = CHECK_CONDITION;
+            status = CHECK_CONDITION;
             scsi_set_sense(s, SENSE_CODE(IO_ERROR));
             break;
         }
     } else {
         if (s->driver_status & SG_ERR_DRIVER_TIMEOUT) {
-            r->req.status = BUSY;
+            status = BUSY;
             BADF("Driver Timeout\n");
-        } else if (r->io_header.status)
-            r->req.status = r->io_header.status;
-        else if (s->driver_status & SG_ERR_DRIVER_SENSE)
-            r->req.status = CHECK_CONDITION;
-        else
-            r->req.status = GOOD;
+        } else if (r->io_header.status) {
+            status = r->io_header.status;
+        } else if (s->driver_status & SG_ERR_DRIVER_SENSE) {
+            status = CHECK_CONDITION;
+        } else {
+            status = GOOD;
+        }
     }
     DPRINTF("Command complete 0x%p tag=0x%x status=%d\n",
-            r, r->req.tag, r->req.status);
+            r, r->req.tag, status);
 
-    scsi_req_complete(&r->req);
+    scsi_req_complete(&r->req, status);
 }
 
 /* Cancel a pending data transfer.  */
@@ -341,8 +343,7 @@  static int32_t scsi_send_command(SCSIRequest *req, uint8_t *cmd)
     if (cmd[0] != REQUEST_SENSE && req->lun != s->lun) {
         DPRINTF("Unimplemented LUN %d\n", req->lun);
         scsi_set_sense(s, SENSE_CODE(LUN_NOT_SUPPORTED));
-        r->req.status = CHECK_CONDITION;
-        scsi_req_complete(&r->req);
+        scsi_req_complete(&r->req, CHECK_CONDITION);
         return 0;
     }
 
diff --git a/hw/scsi.h b/hw/scsi.h
index 6b15bbc..18d3643 100644
--- a/hw/scsi.h
+++ b/hw/scsi.h
@@ -153,7 +153,7 @@  int scsi_req_parse(SCSIRequest *req, uint8_t *buf);
 void scsi_req_print(SCSIRequest *req);
 void scsi_req_continue(SCSIRequest *req);
 void scsi_req_data(SCSIRequest *req, int len);
-void scsi_req_complete(SCSIRequest *req);
+void scsi_req_complete(SCSIRequest *req, int status);
 uint8_t *scsi_req_get_buf(SCSIRequest *req);
 int scsi_req_get_sense(SCSIRequest *req, uint8_t *buf, int len);
 void scsi_req_abort(SCSIRequest *req, int status);