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 --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;
--
2.26.2