[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH v2 03/23] block: Connect BlockBackend to BlockDr
From: |
Markus Armbruster |
Subject: |
Re: [Qemu-devel] [PATCH v2 03/23] block: Connect BlockBackend to BlockDriverState |
Date: |
Mon, 15 Sep 2014 08:59:23 +0200 |
User-agent: |
Gnus/5.13 (Gnus v5.13) Emacs/24.3 (gnu/linux) |
Max Reitz <address@hidden> writes:
> On 13.09.2014 17:00, Markus Armbruster wrote:
>> The pointer from BlockBackend to BlockDriverState is a strong
>> reference, managed with bdrv_ref() / bdrv_unref(), the back-pointer is
>> a weak one.
>>
>> Convenience function blk_new_with_bs() creates a BlockBackend with its
>> BlockDriverState. Callers have to unref both. The commit after next
>> will relieve them of the need to unref the BlockDriverState.
>>
>> Complication: due to the silly way drive_del works, we need a way to
>> hide a BlockBackend, just like bdrv_make_anon(). To emphasize its
>> "special" status, give the function a suitably off-putting name:
>
> So you're trying to force people with a sense of aesthetics to solve
> this problem? I don't know why this isn't taught in Software
> Engineering in university, but it definitely should be.
Ha!
Actually, I only want to deter additional use of this bad idea.
Once we have a decent solution for the problem drive_del is trying to
solve, we can deprecate drive_del, then remove it after a couple of
releases (it's only HMP, not a stable interface). So the solution to
the problem will hopefully be "throw it away".
>> blk_hide_on_behalf_of_do_drive_del(). Unfortunately, hiding turns the
>> BlockBackend's name into the empty string. Can't avoid that without
>> breaking the blk->bs->device_name equals blk->name invariant.
>>
>> Signed-off-by: Markus Armbruster <address@hidden>
>> ---
>> block.c | 10 ++--
>> block/block-backend.c | 70 ++++++++++++++++++++++-
>> blockdev.c | 26 +++------
>> hw/block/xen_disk.c | 8 +--
>> include/block/block_int.h | 2 +
>> include/sysemu/block-backend.h | 5 ++
>> qemu-img.c | 125 +++++++++++++++++++----------------------
>> qemu-io.c | 4 +-
>> qemu-nbd.c | 2 +-
>> 9 files changed, 152 insertions(+), 100 deletions(-)
>
> [snip]
>
>> diff --git a/block/block-backend.c b/block/block-backend.c
>> index 919dd4c..b118b38 100644
>> --- a/block/block-backend.c
>> +++ b/block/block-backend.c
>> @@ -16,10 +16,11 @@
>> struct BlockBackend {
>> char *name;
>> int refcnt;
>> + BlockDriverState *bs;
>> QTAILQ_ENTRY(BlockBackend) link; /* for blk_backends */
>> };
>> -/* All the BlockBackends */
>> +/* All the BlockBackends (except for hidden ones) */
>> static QTAILQ_HEAD(, BlockBackend) blk_backends =
>> QTAILQ_HEAD_INITIALIZER(blk_backends);
>> @@ -47,10 +48,43 @@ BlockBackend *blk_new(const char *name, Error
>> **errp)
>> return blk;
>> }
>> +/*
>> + * Create a new BlockBackend with a new BlockDriverState attached.
>> + * Both have a reference count of one. Caller owns *both* references.
>> + * TODO Let caller own only the BlockBackend reference
>> + * Otherwise just like blk_new(), which see.
>
> Could be my lack of profoundness in English, but I don't understand
> what "which see" is supposed to mean or how its grammar works. An
> imperative?
I guess I picked this up in my reading. Wikipedia recognizes it, so it
must be okay ;-}
https://en.wikipedia.org/wiki/Which_see
>> + */
>> +BlockBackend *blk_new_with_bs(const char *name, Error **errp)
>> +{
>> + BlockBackend *blk;
>> + BlockDriverState *bs;
>> +
>> + blk = blk_new(name, errp);
>> + if (!blk) {
>> + return NULL;
>> + }
>> +
>> + bs = bdrv_new_root(name, errp);
>> + if (!bs) {
>> + blk_unref(blk);
>> + return NULL;
>> + }
>> +
>> + blk->bs = bs;
>> + bs->blk = blk;
>> + return blk;
>> +}
>> +
>
> [snip]
>
>> diff --git a/blockdev.c b/blockdev.c
>> index 5873205..21f4c67 100644
>> --- a/blockdev.c
>> +++ b/blockdev.c
>> @@ -229,14 +229,7 @@ void drive_info_del(DriveInfo *dinfo)
>> qemu_opts_del(dinfo->opts);
>> }
>> - /*
>> - * Hairy special case: if do_drive_del() has made dinfo->bdrv
>> - * anonymous, it also unref'ed the associated BlockBackend.
>> - */
>> - if (dinfo->bdrv->device_name[0]) {
>> - blk_unref(blk_by_name(dinfo->bdrv->device_name));
>> - }
>> -
>> + blk_unref(blk_by_name(dinfo->bdrv->device_name));
>
> So if !device_name[0], the BB is hidden. Hidden BBs are removed from
> the BB list and therefore not returned by blk_by_name(). Therefore,
> the BB is leaked here.
You're right. This part of the patches went through a couple of
iterations already, and at some point I zapped device_name without
realizing it introduces a leak here. I'll try to avoid the zapping.
> I guess this will be fixed up in a later patch, though...
Right again.
>> g_free(dinfo->id);
>> QTAILQ_REMOVE(&drives, dinfo, next);
>> g_free(dinfo->serial);
>
> [snip]
>
>> diff --git a/qemu-nbd.c b/qemu-nbd.c
>> index ff95da6..fa8a7d0 100644
>> --- a/qemu-nbd.c
>> +++ b/qemu-nbd.c
>> @@ -689,7 +689,7 @@ int main(int argc, char **argv)
>> }
>> blk = blk_new("hda", &error_abort);
>> - bs = bdrv_new_root("hda", &error_abort);
>> + bs = blk_bs(blk);
>
> Shouldn't that be a blk_new_with_bs() then, just like every other case?
Fixing...
>> srcpath = argv[optind];
>> ret = bdrv_open(&bs, srcpath, NULL, NULL, flags, drv, &local_err);
Thanks!
- [Qemu-devel] [PATCH v2 02/23] block: New BlockBackend, (continued)
[Qemu-devel] [PATCH v2 08/23] block: Eliminate BlockDriverState member device_name[], Markus Armbruster, 2014/09/13
[Qemu-devel] [PATCH v2 03/23] block: Connect BlockBackend to BlockDriverState, Markus Armbruster, 2014/09/13
[Qemu-devel] [PATCH v2 12/23] virtio-blk: Drop redundant VirtIOBlock member conf, Markus Armbruster, 2014/09/13
[Qemu-devel] [PATCH v2 13/23] virtio-blk: Rename VirtIOBlkConf variables to conf, Markus Armbruster, 2014/09/13
[Qemu-devel] [PATCH v2 01/23] block: Split bdrv_new_root() off bdrv_new(), Markus Armbruster, 2014/09/13
[Qemu-devel] [PATCH v2 06/23] block: Make BlockBackend own its BlockDriverState, Markus Armbruster, 2014/09/13