Make the BlockBackend own the DriveInfo. Change blockdev_init() to return the BlockBackend instead of the DriveInfo.
Signed-off-by: Markus Armbruster <arm...@redhat.com> --- block.c | 3 -- block/block-backend.c | 38 ++++++++++++++++++++++++ blockdev.c | 73 ++++++++++++++++++++++++----------------------- include/sysemu/blockdev.h | 4 +++ 4 files changed, 79 insertions(+), 39 deletions(-) diff --git a/block.c b/block.c index 92f84d2..5708c7c 100644 --- a/block.c +++ b/block.c @@ -29,7 +29,6 @@ #include "qemu/module.h" #include "qapi/qmp/qjson.h" #include "sysemu/sysemu.h" -#include "sysemu/blockdev.h" /* FIXME layering violation */ #include "qemu/notify.h" #include "block/coroutine.h" #include "block/qapi.h" @@ -2121,8 +2120,6 @@ static void bdrv_delete(BlockDriverState *bs) bdrv_close(bs); - drive_info_del(drive_get_by_blockdev(bs)); - /* remove from list, if necessary */ bdrv_make_anon(bs); diff --git a/block/block-backend.c b/block/block-backend.c index b118b38..7b8c062 100644 --- a/block/block-backend.c +++ b/block/block-backend.c @@ -12,11 +12,13 @@ #include "sysemu/block-backend.h" #include "block/block_int.h" +#include "sysemu/blockdev.h" struct BlockBackend { char *name; int refcnt; BlockDriverState *bs; + DriveInfo *legacy_dinfo; QTAILQ_ENTRY(BlockBackend) link; /* for blk_backends */ }; @@ -86,6 +88,7 @@ static void blk_delete(BlockBackend *blk) QTAILQ_REMOVE(&blk_backends, blk, link); } g_free(blk->name); + drive_info_del(blk->legacy_dinfo); g_free(blk); } @@ -165,6 +168,41 @@ BlockDriverState *blk_bs(BlockBackend *blk) } /* + * Return @blk's DriveInfo if any, else null. + */ +DriveInfo *blk_legacy_dinfo(BlockBackend *blk) +{ + return blk->legacy_dinfo; +} + +/* + * Set @blk's DriveInfo to @dinfo, and return it. + * @blk must not have a DriveInfo set already. + * No other BlockBackend may have the same DriveInfo set. + */ +DriveInfo *blk_set_legacy_dinfo(BlockBackend *blk, DriveInfo *dinfo) +{ + assert(!blk->legacy_dinfo); + return blk->legacy_dinfo = dinfo; +} + +/* + * Return the BlockBackend with DriveInfo @dinfo. + * It must exist. + */ +BlockBackend *blk_by_legacy_dinfo(DriveInfo *dinfo) +{ + BlockBackend *blk; + + QTAILQ_FOREACH(blk, &blk_backends, link) { + if (blk->legacy_dinfo == dinfo) { + return blk; + } + } + assert(0); +} + +/* * Hide @blk. * @blk must not have been hidden already. * Make attached BlockDriverState, if any, anonymous. diff --git a/blockdev.c b/blockdev.c index 21f4c67..aec9f0e 100644 --- a/blockdev.c +++ b/blockdev.c @@ -47,8 +47,6 @@ #include "trace.h" #include "sysemu/arch_init.h" -static QTAILQ_HEAD(drivelist, DriveInfo) drives = QTAILQ_HEAD_INITIALIZER(drives); - static const char *const if_name[IF_COUNT] = { [IF_NONE] = "none", [IF_IDE] = "ide", @@ -89,7 +87,8 @@ static const int if_max_devs[IF_COUNT] = { */ void blockdev_mark_auto_del(BlockDriverState *bs) { - DriveInfo *dinfo = drive_get_by_blockdev(bs); + BlockBackend *blk = bs->blk; + DriveInfo *dinfo = blk_legacy_dinfo(blk); if (dinfo && !dinfo->enable_auto_del) { return; @@ -105,7 +104,8 @@ void blockdev_mark_auto_del(BlockDriverState *bs) void blockdev_auto_del(BlockDriverState *bs) { - DriveInfo *dinfo = drive_get_by_blockdev(bs); + BlockBackend *blk = bs->blk; + DriveInfo *dinfo = blk_legacy_dinfo(blk); if (dinfo && dinfo->auto_del) { drive_del(dinfo); @@ -153,15 +153,15 @@ QemuOpts *drive_add(BlockInterfaceType type, int index, const char *file, DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit) { + BlockBackend *blk; DriveInfo *dinfo; - /* seek interface, bus and unit */ - - QTAILQ_FOREACH(dinfo, &drives, next) { - if (dinfo->type == type && - dinfo->bus == bus && - dinfo->unit == unit) + for (blk = blk_next(NULL); blk; blk = blk_next(blk)) { + dinfo = blk_legacy_dinfo(blk); + if (dinfo && dinfo->type == type + && dinfo->bus == bus && dinfo->unit == unit) { return dinfo; + } } return NULL; @@ -177,13 +177,15 @@ DriveInfo *drive_get_by_index(BlockInterfaceType type, int index) int drive_get_max_bus(BlockInterfaceType type) { int max_bus; + BlockBackend *blk; DriveInfo *dinfo; max_bus = -1; - QTAILQ_FOREACH(dinfo, &drives, next) { - if(dinfo->type == type && - dinfo->bus > max_bus) + for (blk = blk_next(NULL); blk; blk = blk_next(blk)) { + dinfo = blk_legacy_dinfo(blk); + if (dinfo && dinfo->type == type && dinfo->bus > max_bus) { max_bus = dinfo->bus; + } } return max_bus; } @@ -200,11 +202,11 @@ DriveInfo *drive_get_next(BlockInterfaceType type) DriveInfo *drive_get_by_blockdev(BlockDriverState *bs) { - DriveInfo *dinfo; + BlockBackend *blk; - QTAILQ_FOREACH(dinfo, &drives, next) { - if (dinfo->bdrv == bs) { - return dinfo; + for (blk = blk_next(NULL); blk; blk = blk_next(blk)) { + if (blk_bs(blk) == bs) { + return blk_legacy_dinfo(blk); } } return NULL; @@ -218,6 +220,7 @@ static void bdrv_format_print(void *opaque, const char *name) void drive_del(DriveInfo *dinfo) { bdrv_unref(dinfo->bdrv); + blk_unref(blk_by_legacy_dinfo(dinfo)); } void drive_info_del(DriveInfo *dinfo) @@ -228,10 +231,7 @@ void drive_info_del(DriveInfo *dinfo) if (dinfo->opts) { qemu_opts_del(dinfo->opts); } - - blk_unref(blk_by_name(dinfo->bdrv->device_name)); g_free(dinfo->id); - QTAILQ_REMOVE(&drives, dinfo, next); g_free(dinfo->serial); g_free(dinfo); } @@ -303,8 +303,8 @@ static bool check_throttle_config(ThrottleConfig *cfg, Error **errp) typedef enum { MEDIA_DISK, MEDIA_CDROM } DriveMediaType; /* Takes the ownership of bs_opts */ -static DriveInfo *blockdev_init(const char *file, QDict *bs_opts, - Error **errp) +static BlockBackend *blockdev_init(const char *file, QDict *bs_opts, + Error **errp) { const char *buf; int ro = 0; @@ -487,7 +487,7 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts, dinfo = g_malloc0(sizeof(*dinfo)); dinfo->id = g_strdup(qemu_opts_id(opts)); dinfo->bdrv = bs; - QTAILQ_INSERT_TAIL(&drives, dinfo, next); + blk_set_legacy_dinfo(blk, dinfo); if (!file || !*file) { if (has_driver_specific_opts) { @@ -495,7 +495,7 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts, } else { QDECREF(bs_opts); qemu_opts_del(opts); - return dinfo; + return blk; } } if (snapshot) { @@ -532,7 +532,7 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts, QDECREF(bs_opts); qemu_opts_del(opts); - return dinfo; + return blk; err: bdrv_unref(bs); @@ -639,6 +639,7 @@ QemuOptsList qemu_legacy_drive_opts = { DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type) { const char *value; + BlockBackend *blk; DriveInfo *dinfo = NULL; QDict *bs_opts; QemuOpts *legacy_opts; @@ -921,19 +922,18 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type) } /* Actual block device init: Functionality shared with blockdev-add */ - dinfo = blockdev_init(filename, bs_opts, &local_err); + blk = blockdev_init(filename, bs_opts, &local_err); bs_opts = NULL; - if (dinfo == NULL) { - if (local_err) { - error_report("%s", error_get_pretty(local_err)); - error_free(local_err); - } + if (!blk) { + error_report("%s", error_get_pretty(local_err)); + error_free(local_err); goto fail; } else { assert(!local_err); } /* Set legacy DriveInfo fields */ + dinfo = blk_legacy_dinfo(blk); dinfo->enable_auto_del = true; dinfo->opts = all_opts; @@ -1763,7 +1763,7 @@ int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data) } bs = blk_bs(blk); - dinfo = drive_get_by_blockdev(bs); + dinfo = blk_legacy_dinfo(blk); if (dinfo && !dinfo->enable_auto_del) { error_report("Deleting device added with blockdev-add" " is not supported"); @@ -2488,7 +2488,7 @@ void qmp_change_backing_file(const char *device, void qmp_blockdev_add(BlockdevOptions *options, Error **errp) { QmpOutputVisitor *ov = qmp_output_visitor_new(); - DriveInfo *dinfo; + BlockBackend *blk; QObject *obj; QDict *qdict; Error *local_err = NULL; @@ -2526,14 +2526,15 @@ void qmp_blockdev_add(BlockdevOptions *options, Error **errp) qdict_flatten(qdict); - dinfo = blockdev_init(NULL, qdict, &local_err); + blk = blockdev_init(NULL, qdict, &local_err); if (local_err) { error_propagate(errp, local_err); goto fail; } - if (bdrv_key_required(dinfo->bdrv)) { - drive_del(dinfo); + if (bdrv_key_required(blk_bs(blk))) { + bdrv_unref(blk_bs(blk)); + blk_unref(blk); error_setg(errp, "blockdev-add doesn't support encrypted devices"); goto fail; } diff --git a/include/sysemu/blockdev.h b/include/sysemu/blockdev.h index abec381..1dc5906 100644 --- a/include/sysemu/blockdev.h +++ b/include/sysemu/blockdev.h @@ -45,6 +45,10 @@ struct DriveInfo { QTAILQ_ENTRY(DriveInfo) next; }; +DriveInfo *blk_legacy_dinfo(BlockBackend *blk); +DriveInfo *blk_set_legacy_dinfo(BlockBackend *blk, DriveInfo *dinfo); +BlockBackend *blk_by_legacy_dinfo(DriveInfo *dinfo); + DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit); DriveInfo *drive_get_by_index(BlockInterfaceType type, int index); int drive_get_max_bus(BlockInterfaceType type); -- 1.9.3