Add scsi_device_get which finds the scsi device and takes a reference to it.
Suggested-by: Stefan Hajnoczi <stefa...@gmail.com> Signed-off-by: Maxim Levitsky <mlevi...@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