The monitor does hold references to some BlockBackends so it should have a list of those BBs; blk_backends is a different list, as it contains references to all BBs (after a follow-up patch, that is), and that should not be changed because we do need such a list.
Signed-off-by: Max Reitz <mre...@redhat.com> --- block/block-backend.c | 27 ++++++++++++++++++++++++++- blockdev.c | 14 ++++++++++++++ include/sysemu/block-backend.h | 2 ++ 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/block/block-backend.c b/block/block-backend.c index f136fc8..c5ca0f4 100644 --- a/block/block-backend.c +++ b/block/block-backend.c @@ -28,6 +28,7 @@ struct BlockBackend { BlockDriverState *bs; DriveInfo *legacy_dinfo; /* null unless created by drive_new() */ QTAILQ_ENTRY(BlockBackend) link; /* for blk_backends */ + QTAILQ_ENTRY(BlockBackend) monitor_link; /* for monitor_block_backends */ void *dev; /* attached device model, if any */ /* TODO change to DeviceState when all users are qdevified */ @@ -67,6 +68,11 @@ static void drive_info_del(DriveInfo *dinfo); static QTAILQ_HEAD(, BlockBackend) blk_backends = QTAILQ_HEAD_INITIALIZER(blk_backends); +/* All BlockBackends referenced by the monitor and which are iterated through by + * blk_next() */ +static QTAILQ_HEAD(, BlockBackend) monitor_block_backends = + QTAILQ_HEAD_INITIALIZER(monitor_block_backends); + /* * Create a new BlockBackend with @name, with a reference count of one. * @name must not be null or empty. @@ -228,7 +234,8 @@ void blk_unref(BlockBackend *blk, Notifier *close_all_notifier) */ BlockBackend *blk_next(BlockBackend *blk) { - return blk ? QTAILQ_NEXT(blk, link) : QTAILQ_FIRST(&blk_backends); + return blk ? QTAILQ_NEXT(blk, monitor_link) + : QTAILQ_FIRST(&monitor_block_backends); } /* @@ -247,6 +254,24 @@ BlockBackend *blk_next_inserted(BlockBackend *blk) } /* + * Add a BlockBackend into the list of backends referenced by the monitor. + * Strictly for use by blockdev.c. + */ +void monitor_add_blk(BlockBackend *blk) +{ + QTAILQ_INSERT_TAIL(&monitor_block_backends, blk, monitor_link); +} + +/* + * Remove a BlockBackend from the list of backends referenced by the monitor. + * Strictly for use by blockdev.c. + */ +void monitor_remove_blk(BlockBackend *blk) +{ + QTAILQ_REMOVE(&monitor_block_backends, blk, monitor_link); +} + +/* * Return @blk's name, a non-null string. * Wart: the name is empty iff @blk has been hidden with * blk_hide_on_behalf_of_do_drive_del(). diff --git a/blockdev.c b/blockdev.c index 22d7ceb..0f965bd 100644 --- a/blockdev.c +++ b/blockdev.c @@ -90,6 +90,8 @@ static int if_max_devs[IF_COUNT] = { static void monitor_blk_unref_with_can(BlockBackend *blk, BlockdevCloseAllNotifier *can) { + BlockBackend *blk1 = NULL; + if (can) { assert(can->blk == blk); } else { @@ -101,6 +103,15 @@ static void monitor_blk_unref_with_can(BlockBackend *blk, assert(can); } + /* Thanks to do_drive_del() magic, the BlockBackend is not necessarily + * listed at this point */ + while ((blk1 = blk_next(blk1)) != NULL) { + if (blk1 == blk) { + monitor_remove_blk(blk); + break; + } + } + blk_unref(blk, &can->n); QTAILQ_REMOVE(&close_all_notifiers, can, next); g_free(can); @@ -634,6 +645,8 @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts, blk_set_on_error(blk, on_read_error, on_write_error); + monitor_add_blk(blk); + err_no_bs_opts: qemu_opts_del(opts); return blk; @@ -2294,6 +2307,7 @@ int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data) */ if (blk_get_attached_dev(blk)) { blk_hide_on_behalf_of_do_drive_del(blk); + monitor_remove_blk(blk); /* Further I/O must not pause the guest */ blk_set_on_error(blk, BLOCKDEV_ON_ERROR_REPORT, BLOCKDEV_ON_ERROR_REPORT); diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h index 73b26ad..1683732 100644 --- a/include/sysemu/block-backend.h +++ b/include/sysemu/block-backend.h @@ -75,6 +75,8 @@ BlockBackend *blk_by_name(const char *name); bool blk_name_taken(const char *name); BlockBackend *blk_next(BlockBackend *blk); BlockBackend *blk_next_inserted(BlockBackend *blk); +void monitor_add_blk(BlockBackend *blk); +void monitor_remove_blk(BlockBackend *blk); BlockDriverState *blk_bs(BlockBackend *blk); void blk_remove_bs(BlockBackend *blk); -- 2.1.0