diff mbox series

[v2,6/7] scsi: Add scsi_device_get

Message ID 20200511160951.8733-7-mlevitsk@redhat.com (mailing list archive)
State New, archived
Headers show
Series RFC/WIP: Fix scsi devices plug/unplug races w.r.t virtio-scsi iothread | expand

Commit Message

Maxim Levitsky May 11, 2020, 4:09 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     | 31 ++++++++++++++++++++++++-------
 include/hw/scsi/scsi.h |  2 ++
 2 files changed, 26 insertions(+), 7 deletions(-)

Comments

Stefan Hajnoczi May 27, 2020, 3:27 p.m. UTC | #1
On Mon, May 11, 2020 at 07:09:50PM +0300, Maxim Levitsky wrote:
> +/*
> + * This function works like scsi_device_get but doesn't take a refernce

s/refernce/reference/

> + * to the returned object. Intended for legacy code

The following explains this in more detail. It's not necessarily legacy
code but rather whether it runs under the QEMU global mutex or not:

Devices that run under the QEMU global mutex can use this function.
Devices that run outside the QEMU global mutex must use
scsi_device_get() instead.
Maxim Levitsky July 9, 2020, 10:35 a.m. UTC | #2
On Wed, 2020-05-27 at 16:27 +0100, Stefan Hajnoczi wrote:
> On Mon, May 11, 2020 at 07:09:50PM +0300, Maxim Levitsky wrote:
> > +/*
> > + * This function works like scsi_device_get but doesn't take a refernce
> 
> s/refernce/reference/
> 
> > + * to the returned object. Intended for legacy code
> 
> The following explains this in more detail. It's not necessarily legacy
> code but rather whether it runs under the QEMU global mutex or not:
> 
> Devices that run under the QEMU global mutex can use this function.
> Devices that run outside the QEMU global mutex must use
> scsi_device_get() instead.
Done.

Best regards,
	Maxim Levitsky
diff mbox series

Patch

diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c
index 2bf6d005f3..4e15de0bd7 100644
--- a/hw/scsi/scsi-bus.c
+++ b/hw/scsi/scsi-bus.c
@@ -1584,8 +1584,13 @@  static char *scsibus_get_fw_dev_path(DeviceState *dev)
     return g_strdup_printf("channel@%x/%s@%x,%x", d->channel,
                            qdev_fw_name(dev), d->id, d->lun);
 }
-
-SCSIDevice *scsi_device_find(SCSIBus *bus, int channel, int id, int lun)
+/*
+ * Finds a matching channel/id/lun device on scsi bus, and
+ * takes a reference to it and returns it.
+ * If we don't find exact match (channel/bus/lun),
+ * we will return the first device which matches channel/bus
+ * */
+SCSIDevice *scsi_device_get(SCSIBus *bus, int channel, int id, int lun)
 {
     BusChild *kid;
     SCSIDevice *target_dev = NULL;
@@ -1598,25 +1603,37 @@  SCSIDevice *scsi_device_find(SCSIBus *bus, int channel, int id, int lun)
 
         if (dev->channel == channel && dev->id == id) {
             if (dev->lun == lun) {
+                object_ref(OBJECT(dev));
                 rcu_read_unlock();
                 return dev;
             }
 
-            /*
-             * If we don't find exact match (channel/bus/lun),
-             * we will return the first device which matches channel/bus
-             */
-
             if (!target_dev) {
                 target_dev = dev;
             }
         }
     }
 
+    object_ref(OBJECT(target_dev));
     rcu_read_unlock();
     return target_dev;
 }
 
+/*
+ * This function works like scsi_device_get but doesn't take a refernce
+ * to the returned object. Intended for legacy code
+ */
+SCSIDevice *scsi_device_find(SCSIBus *bus, int channel, int id, int lun)
+{
+    SCSIDevice *dev = scsi_device_get(bus, channel, id, lun);
+
+    if (!dev)
+        return NULL;
+
+    object_unref(OBJECT(dev));
+    return dev;
+}
+
 /* SCSI request list.  For simplicity, pv points to the whole device */
 
 static int put_scsi_requests(QEMUFile *f, void *pv, size_t size,
diff --git a/include/hw/scsi/scsi.h b/include/hw/scsi/scsi.h
index 332ef602f4..5e1d31ab6d 100644
--- a/include/hw/scsi/scsi.h
+++ b/include/hw/scsi/scsi.h
@@ -193,7 +193,9 @@  void scsi_generic_read_device_inquiry(SCSIDevice *dev);
 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;