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/block-backend.c | 38 +++++++++++++++++++++++ blockdev.c | 79 +++++++++++++++++++++-------------------------- include/sysemu/blockdev.h | 4 +++ 3 files changed, 78 insertions(+), 43 deletions(-) diff --git a/block/block-backend.c b/block/block-backend.c index deccb54..2a22660 100644 --- a/block/block-backend.c +++ b/block/block-backend.c @@ -12,14 +12,18 @@ #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 */ }; +static void drive_info_del(DriveInfo *dinfo); + static QTAILQ_HEAD(, BlockBackend) blk_backends = QTAILQ_HEAD_INITIALIZER(blk_backends); @@ -87,6 +91,7 @@ static void blk_delete(BlockBackend *blk) blk_detach_bs(blk); QTAILQ_REMOVE(&blk_backends, blk, link); g_free(blk->name); + drive_info_del(blk->legacy_dinfo); g_free(blk); } @@ -119,6 +124,16 @@ void blk_unref(BlockBackend *blk) } } +static void drive_info_del(DriveInfo *dinfo) +{ + if (dinfo) { + qemu_opts_del(dinfo->opts); + g_free(dinfo->id); + g_free(dinfo->serial); + g_free(dinfo); + } +} + const char *blk_name(BlockBackend *blk) { return blk->name; @@ -187,3 +202,26 @@ BlockDriverState *blk_detach_bs(BlockBackend *blk) } return bs; } + +DriveInfo *blk_legacy_dinfo(BlockBackend *blk) +{ + return blk->legacy_dinfo; +} + +DriveInfo *blk_set_legacy_dinfo(BlockBackend *blk, DriveInfo *dinfo) +{ + assert(!blk->legacy_dinfo); + return blk->legacy_dinfo = dinfo; +} + +BlockBackend *blk_by_legacy_dinfo(DriveInfo *dinfo) +{ + BlockBackend *blk; + + QTAILQ_FOREACH(blk, &blk_backends, link) { + if (blk->legacy_dinfo == dinfo) { + return blk; + } + } + assert(0); +} diff --git a/blockdev.c b/blockdev.c index 0a0b95e..73e2da9 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; @@ -217,16 +219,10 @@ static void bdrv_format_print(void *opaque, const char *name) void drive_del(DriveInfo *dinfo) { - if (dinfo->opts) { - qemu_opts_del(dinfo->opts); - } + BlockBackend *blk = dinfo->bdrv->blk; bdrv_unref(dinfo->bdrv); - blk_unref(blk_by_name(dinfo->id)); - g_free(dinfo->id); - QTAILQ_REMOVE(&drives, dinfo, next); - g_free(dinfo->serial); - g_free(dinfo); + blk_unref(blk); } typedef struct { @@ -296,8 +292,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; @@ -480,7 +476,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) { @@ -488,7 +484,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) { @@ -525,13 +521,10 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts, QDECREF(bs_opts); qemu_opts_del(opts); - return dinfo; + return blk; err: bdrv_unref(dinfo->bdrv); - QTAILQ_REMOVE(&drives, dinfo, next); - g_free(dinfo->id); - g_free(dinfo); blk_unref(blk); early_err: qemu_opts_del(opts); @@ -635,6 +628,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; @@ -917,19 +911,17 @@ 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)); goto fail; } else { assert(!local_err); } /* Set legacy DriveInfo fields */ + dinfo = blk_legacy_dinfo(blk); dinfo->enable_auto_del = true; dinfo->opts = all_opts; @@ -2478,7 +2470,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; @@ -2516,14 +2508,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 23a5d10..2ed297b 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