summary refs log tree commit diff stats
path: root/hw/scsi
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2013-06-03 14:09:39 +0200
committerPaolo Bonzini <pbonzini@redhat.com>2013-07-04 17:37:30 +0200
commitcac3c384bb986f06a308e551641284586924813c (patch)
tree46f90acd8f2446d5716212ac6d82a0451f3c7e5c /hw/scsi
parent6046c620866f6f5c53eaece9f4ad8d44a12e1185 (diff)
downloadfocaccia-qemu-cac3c384bb986f06a308e551641284586924813c.tar.gz
focaccia-qemu-cac3c384bb986f06a308e551641284586924813c.zip
scsi: keep device alive while it has requests
Reviewed-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'hw/scsi')
-rw-r--r--hw/scsi/scsi-bus.c12
1 files changed, 10 insertions, 2 deletions
diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c
index 53ea906433..a92b7c1de4 100644
--- a/hw/scsi/scsi-bus.c
+++ b/hw/scsi/scsi-bus.c
@@ -505,10 +505,12 @@ SCSIRequest *scsi_req_alloc(const SCSIReqOps *reqops, SCSIDevice *d,
                             uint32_t tag, uint32_t lun, void *hba_private)
 {
     SCSIRequest *req;
+    SCSIBus *bus = scsi_bus_from_device(d);
+    BusState *qbus = BUS(bus);
 
     req = g_malloc0(reqops->size);
     req->refcount = 1;
-    req->bus = scsi_bus_from_device(d);
+    req->bus = bus;
     req->dev = d;
     req->tag = tag;
     req->lun = lun;
@@ -516,6 +518,8 @@ SCSIRequest *scsi_req_alloc(const SCSIReqOps *reqops, SCSIDevice *d,
     req->status = -1;
     req->sense_len = 0;
     req->ops = reqops;
+    object_ref(OBJECT(d));
+    object_ref(OBJECT(qbus->parent));
     trace_scsi_req_alloc(req->dev->id, req->lun, req->tag);
     return req;
 }
@@ -1498,13 +1502,17 @@ void scsi_req_unref(SCSIRequest *req)
 {
     assert(req->refcount > 0);
     if (--req->refcount == 0) {
-        SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, req->dev->qdev.parent_bus);
+        BusState *qbus = req->dev->qdev.parent_bus;
+        SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, qbus);
+
         if (bus->info->free_request && req->hba_private) {
             bus->info->free_request(bus, req->hba_private);
         }
         if (req->ops->free_req) {
             req->ops->free_req(req);
         }
+        object_unref(OBJECT(req->dev));
+        object_unref(OBJECT(qbus->parent));
         g_free(req);
     }
 }