diff mbox series

[v4,7/9] scsi/scsi_bus: Add scsi_device_get

Message ID 20200831150124.206267-8-mlevitsk@redhat.com
State New
Headers show
Series Fix scsi devices plug/unplug races w.r.t virtio-scsi iothread | expand

Commit Message

Maxim Levitsky Aug. 31, 2020, 3:01 p.m. UTC
Add scsi_device_get which finds the scsi device
and takes a reference to it.

Suggested-by: Stefan Hajnoczi <stefanha@gmail.com>
Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com>
---
 hw/scsi/scsi-bus.c     | 22 +++++++++++++++++-----
 include/hw/scsi/scsi.h |  1 +
 2 files changed, 18 insertions(+), 5 deletions(-)
diff mbox series

Patch

diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c
index 7ceae2c92b..feab20b76d 100644
--- a/hw/scsi/scsi-bus.c
+++ b/hw/scsi/scsi-bus.c
@@ -52,7 +52,7 @@  static const TypeInfo scsi_bus_info = {
 static int next_scsi_bus;
 
 static SCSIDevice *_scsi_device_find(SCSIBus *bus, int channel, int id, int lun,
-                                     bool include_unrealized)
+                                     bool include_unrealized, bool take_ref)
 {
     BusChild *kid;
     SCSIDevice *retval = NULL;
@@ -92,13 +92,22 @@  out:
         retval = NULL;
     }
 
+    if (take_ref) {
+        object_ref(OBJECT(retval));
+    }
+
     rcu_read_unlock();
     return retval;
 }
 
 SCSIDevice *scsi_device_find(SCSIBus *bus, int channel, int id, int lun)
 {
-    return _scsi_device_find(bus, channel, id, lun, false);
+    return _scsi_device_find(bus, channel, id, lun, false, false);
+}
+
+SCSIDevice *scsi_device_get(SCSIBus *bus, int channel, int id, int lun)
+{
+    return _scsi_device_find(bus, channel, id, lun, false, true);
 }
 
 static void scsi_device_realize(SCSIDevice *s, Error **errp)
@@ -236,7 +245,8 @@  static void scsi_qdev_realize(DeviceState *qdev, Error **errp)
             dev->lun = 0;
         }
         do {
-            d = _scsi_device_find(bus, dev->channel, ++id, dev->lun, true);
+            d = _scsi_device_find(bus, dev->channel, ++id, dev->lun,
+                                  true, false);
         } while (d && d->lun == dev->lun && id < bus->info->max_target);
         if (d && d->lun == dev->lun) {
             error_setg(errp, "no free target");
@@ -246,7 +256,8 @@  static void scsi_qdev_realize(DeviceState *qdev, Error **errp)
     } else if (dev->lun == -1) {
         int lun = -1;
         do {
-            d = _scsi_device_find(bus, dev->channel, dev->id, ++lun, true);
+            d = _scsi_device_find(bus, dev->channel, dev->id, ++lun,
+                                 true, false);
         } while (d && d->lun == lun && lun < bus->info->max_lun);
         if (d && d->lun == lun) {
             error_setg(errp, "no free lun");
@@ -254,7 +265,8 @@  static void scsi_qdev_realize(DeviceState *qdev, Error **errp)
         }
         dev->lun = lun;
     } else {
-        d = _scsi_device_find(bus, dev->channel, dev->id, dev->lun, true);
+        d = _scsi_device_find(bus, dev->channel, dev->id, dev->lun,
+                              true, false);
         assert(d);
         if (d->lun == dev->lun && dev != d) {
             error_setg(errp, "lun already used by '%s'", d->qdev.id);
diff --git a/include/hw/scsi/scsi.h b/include/hw/scsi/scsi.h
index 2fc23e44ba..e939a81789 100644
--- a/include/hw/scsi/scsi.h
+++ b/include/hw/scsi/scsi.h
@@ -194,6 +194,7 @@  int scsi_device_get_sense(SCSIDevice *dev, uint8_t *buf, int len, bool fixed);
 int scsi_SG_IO_FROM_DEV(BlockBackend *blk, uint8_t *cmd, uint8_t cmd_size,
                         uint8_t *buf, uint8_t buf_size);
 SCSIDevice *scsi_device_find(SCSIBus *bus, int channel, int target, int lun);
+SCSIDevice *scsi_device_get(SCSIBus *bus, int channel, int target, int lun);
 
 /* scsi-generic.c. */
 extern const SCSIReqOps scsi_generic_req_ops;