[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH v3 04/23] block: Connect BlockBackend and DriveI
From: |
Kevin Wolf |
Subject: |
Re: [Qemu-devel] [PATCH v3 04/23] block: Connect BlockBackend and DriveInfo |
Date: |
Mon, 22 Sep 2014 19:15:32 +0200 |
User-agent: |
Mutt/1.5.21 (2010-09-15) |
Am 16.09.2014 um 20:12 hat Markus Armbruster geschrieben:
> Make the BlockBackend own the DriveInfo. Change blockdev_init() to
> return the BlockBackend instead of the DriveInfo.
>
> Signed-off-by: Markus Armbruster <address@hidden>
> ---
> block.c | 2 --
> block/block-backend.c | 38 ++++++++++++++++++++++++
> blockdev.c | 73
> ++++++++++++++++++++++++-----------------------
> include/sysemu/blockdev.h | 4 +++
> 4 files changed, 79 insertions(+), 38 deletions(-)
>
> diff --git a/block.c b/block.c
> index 7ccf443..5f7dc45 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"
> @@ -2124,7 +2123,6 @@ static void bdrv_delete(BlockDriverState *bs)
> /* remove from list, if necessary */
> bdrv_make_anon(bs);
>
> - drive_info_del(drive_get_by_blockdev(bs));
> g_free(bs);
> }
>
> diff --git a/block/block-backend.c b/block/block-backend.c
> index a12215a..9ee57c7 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 */
> };
>
> @@ -87,6 +89,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);
> }
>
> @@ -167,6 +170,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;
Ugh, I don't like assignments in a return statement much more than
setters that return something.
Fortunately, nobody uses the return value, so this can become a void
function.
> +}
> +/*
> + * 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);
I'm surprised that the compiler doesn't complain here. Seems it
understands that the condition is always false and the libc header sets
the noreturn attribute for the internal function handling a failure.
With NDEBUG set, this wouldn't work any more.
I think abort() is better.
> +}
> +
> +/*
> * Hide @blk.
> * @blk must not have been hidden already.
> * Make attached BlockDriverState, if any, anonymous.
> diff --git a/blockdev.c b/blockdev.c
> index 5da6028..722d083 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;
Why don't you use bs->blk here?
Also, why replace calls to drive_get_by_blockdev() above when the
function stays? Wouldn't it make more sense to remove all callers in a
single patch instead of doing part of it in an unrelated patch?
> @@ -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));
> }
Hmm, let's see. drive_del() has four callers:
* do_drive_del(): A blk_unref() is removed there, so the code remains
equivalent. Good.
* blockdev_auto_del(): Here, the blk_unref() is new. If I'm reading the
code right, unplugging a device doesn't only automagically destroy the
DriveInfo now, but also the BlockBackend. Is this really magic that we
want BlockBackend to inherit? (I don't think so.)
* drive_hot_add(): This is an error paths that frees a previously leaked
BlockBackend created by an indirect drive_new() call. Silent bug fix?
* pci_piix3_xen_ide_unplug(): Xen magic I don't fully understand. The
guest can tell us to remove the IDE drives (because it sees the same
image through the PV driver, I think). Whether or not we want to
remove the BlockBackend, I'm not completely sure.
Kevin
- Re: [Qemu-devel] [PATCH v3 07/23] block: Eliminate bdrv_iterate(), use bdrv_next(), (continued)
- [Qemu-devel] [PATCH v3 10/23] block: Eliminate DriveInfo member bdrv, use blk_by_legacy_dinfo(), Markus Armbruster, 2014/09/16
- [Qemu-devel] [PATCH v3 04/23] block: Connect BlockBackend and DriveInfo, Markus Armbruster, 2014/09/16
- [Qemu-devel] [PATCH v3 08/23] block: Eliminate BlockDriverState member device_name[], Markus Armbruster, 2014/09/16
- [Qemu-devel] [PATCH v3 13/23] virtio-blk: Rename VirtIOBlkConf variables to conf, Markus Armbruster, 2014/09/16
- [Qemu-devel] [PATCH v3 06/23] block: Make BlockBackend own its BlockDriverState, Markus Armbruster, 2014/09/16