Instead of delaying blk_detach_dev and blockdev_auto_del until the object is finalized and properties are released, do that as soon as possible.
This patch replaces blockdev_mark_auto_del calls with blk_detach_dev and blockdev_del_drive (the latter is a combination of the former blockdev_mark_auto_del and blockdev_auto_del). We cannot make blk_detach_dev do both tasks because of the USB mass storage hack. Signed-off-by: Paolo Bonzini <pbonz...@redhat.com> --- blockdev.c | 21 +++++---------------- hw/block/virtio-blk.c | 4 +++- hw/block/xen_disk.c | 1 + hw/core/qdev-properties-system.c | 2 +- hw/ide/piix.c | 3 +++ hw/scsi/scsi-bus.c | 4 +++- hw/usb/dev-storage.c | 3 ++- include/sysemu/blockdev.h | 4 +--- 8 files changed, 19 insertions(+), 23 deletions(-) diff --git a/blockdev.c b/blockdev.c index 917ae06..a8309fb 100644 --- a/blockdev.c +++ b/blockdev.c @@ -110,20 +110,16 @@ void override_max_devs(BlockInterfaceType type, int max_devs) /* * We automatically delete the drive when a device using it gets * unplugged. Questionable feature, but we can't just drop it. - * Device models call blockdev_mark_auto_del() to schedule the - * automatic deletion, and generic qdev code calls blockdev_auto_del() - * when deletion is actually safe. + * Device models call blockdev_del_drive() to schedule the + * automatic deletion, and generic block layer code uses the + * refcount to do the deletion when it is actually safe. */ -void blockdev_mark_auto_del(BlockBackend *blk) +void blockdev_del_drive(BlockBackend *blk) { DriveInfo *dinfo = blk_legacy_dinfo(blk); BlockDriverState *bs = blk_bs(blk); AioContext *aio_context; - if (!dinfo) { - return; - } - if (bs) { aio_context = bdrv_get_aio_context(bs); aio_context_acquire(aio_context); @@ -135,14 +131,7 @@ void blockdev_mark_auto_del(BlockBackend *blk) aio_context_release(aio_context); } - dinfo->auto_del = 1; -} - -void blockdev_auto_del(BlockBackend *blk) -{ - DriveInfo *dinfo = blk_legacy_dinfo(blk); - - if (dinfo && dinfo->auto_del) { + if (dinfo) { blk_unref(blk); } } diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c index 848f3fe..6e51246 100644 --- a/hw/block/virtio-blk.c +++ b/hw/block/virtio-blk.c @@ -960,7 +960,9 @@ static void virtio_blk_device_unrealize(DeviceState *dev, Error **errp) s->dataplane = NULL; qemu_del_vm_change_state_handler(s->change); unregister_savevm(dev, "virtio-blk", s); - blockdev_mark_auto_del(s->blk); + blk_detach_dev(s->blk, dev); + blockdev_del_drive(s->blk); + s->blk = NULL; virtio_cleanup(vdev); } diff --git a/hw/block/xen_disk.c b/hw/block/xen_disk.c index 02eda6e..a6a0b7c 100644 --- a/hw/block/xen_disk.c +++ b/hw/block/xen_disk.c @@ -1054,6 +1054,7 @@ static void blk_disconnect(struct XenDevice *xendev) if (blkdev->blk) { blk_detach_dev(blkdev->blk, blkdev); + blockdev_del_drive(blkdev->blk); blk_unref(blkdev->blk); blkdev->blk = NULL; } diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c index 921e799..cf147f4 100644 --- a/hw/core/qdev-properties-system.c +++ b/hw/core/qdev-properties-system.c @@ -102,7 +102,7 @@ static void release_drive(Object *obj, const char *name, void *opaque) if (*ptr) { blk_detach_dev(*ptr, dev); - blockdev_auto_del(*ptr); + blockdev_del_drive(*ptr); } } diff --git a/hw/ide/piix.c b/hw/ide/piix.c index 5a26c86..2b2d043 100644 --- a/hw/ide/piix.c +++ b/hw/ide/piix.c @@ -181,6 +181,9 @@ int pci_piix3_xen_ide_unplug(DeviceState *dev) if (ds) { blk_detach_dev(blk, ds); } + if (pci_ide->bus[di->bus].ifs[di->unit].blk) { + blockdev_del_drive(blk); + } pci_ide->bus[di->bus].ifs[di->unit].blk = NULL; if (!(i % 2)) { idedev = pci_ide->bus[di->bus].master; diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c index fd1171e..a805fad 100644 --- a/hw/scsi/scsi-bus.c +++ b/hw/scsi/scsi-bus.c @@ -213,7 +213,9 @@ static void scsi_qdev_unrealize(DeviceState *qdev, Error **errp) } scsi_device_purge_requests(dev, SENSE_CODE(NO_SENSE)); - blockdev_mark_auto_del(dev->conf.blk); + blk_detach_dev(dev->conf.blk, qdev); + blockdev_del_drive(dev->conf.blk); + dev->conf.blk = NULL; } /* handle legacy '-drive if=scsi,...' cmd line args */ diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c index 597d8fd..f191011 100644 --- a/hw/usb/dev-storage.c +++ b/hw/usb/dev-storage.c @@ -642,7 +642,8 @@ static void usb_msd_realize_storage(USBDevice *dev, Error **errp) * blockdev, or else scsi_bus_legacy_add_drive() dies when it * attaches again. * - * The hack is probably a bad idea. + * The hack is probably a bad idea. Anyway, this is why this does not + * call blockdev_del_drive. */ blk_detach_dev(blk, &s->dev.qdev); s->conf.blk = NULL; diff --git a/include/sysemu/blockdev.h b/include/sysemu/blockdev.h index b06a060..ae7ad67 100644 --- a/include/sysemu/blockdev.h +++ b/include/sysemu/blockdev.h @@ -14,8 +14,7 @@ #include "qapi/error.h" #include "qemu/queue.h" -void blockdev_mark_auto_del(BlockBackend *blk); -void blockdev_auto_del(BlockBackend *blk); +void blockdev_del_drive(BlockBackend *blk); typedef enum { IF_DEFAULT = -1, /* for use with drive_add() only */ @@ -34,7 +33,6 @@ struct DriveInfo { BlockInterfaceType type; int bus; int unit; - int auto_del; /* see blockdev_mark_auto_del() */ bool is_default; /* Added by default_drive() ? */ int media_cd; int cyls, heads, secs, trans; -- 2.5.0