qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH v2 02/23] block: New BlockBackend


From: Markus Armbruster
Subject: Re: [Qemu-devel] [PATCH v2 02/23] block: New BlockBackend
Date: Mon, 15 Sep 2014 15:53:45 +0200
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/24.3 (gnu/linux)

Benoît Canet <address@hidden> writes:

>> --- a/block.c
>> +++ b/block.c
>> @@ -2119,10 +2119,11 @@ 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);
>>  
>> -    drive_info_del(drive_get_by_blockdev(bs));
>
> Do we really want this move ?

Yes, we do.  If bdrv_make_anon() runs before drive_info_del(), this
conditional in drive_info_del() is always false:

    if (dinfo->bdrv->device_name[0]) {
        blk_unref(blk_by_name(dinfo->bdrv->device_name));
    }

I apologize for the hairiness.  Things will become *way* simpler in
PATCH 4.

> Or is it an artefact of your work on the preparation series ?

I added the line in "[PATCH 2/4] block: Keep DriveInfo alive until
BlockDriverState dies" in the wrong place for this patch, so I have to
move it here.  When I noticed, the patch was already out.  If I have to
respin, I'll avoid the churn.

>>      g_free(bs);
>>  }
>>  
>
>> + * Return the BlockBackend with name @name if it exists, else null.
>
>> + * @name must not be null.
> The contract is that no one will call blk_by_name(NULL);
>
>> + */
>> +BlockBackend *blk_by_name(const char *name)
>> +{
>> +    BlockBackend *blk;
>
> Can we ?
>
>      assert(name);

Sure, why not.

>> +
>> +    QTAILQ_FOREACH(blk, &blk_backends, link) {
>> +        if (!strcmp(name, blk->name)) {
>> +            return blk;
>> +        }
>> +    }
>> +    return NULL;
>> +}
[...]
>> @@ -227,6 +228,15 @@ void drive_info_del(DriveInfo *dinfo)
>>      if (dinfo->opts) {
>>          qemu_opts_del(dinfo->opts);
>>      }
>> +    /*
>> +     * Hairy special case: if do_drive_del() has made dinfo->bdrv
>> +     * anonymous, it also unref'ed the associated BlockBackend.
>> +     */
>
> Then you are filling the other case here.
>
> maybe
>
>     /*
>      * Hairy special case: if do_drive_del() has made dinfo->bdrv
>      * anonymous, it also unref'ed the associated BlockBackend.
>      * Process the other case here.
>      */
>
> would further explain you intents.

Okay.

>> +    if (dinfo->bdrv->device_name[0]) {
>> +        blk_unref(blk_by_name(dinfo->bdrv->device_name));
>> +    }
>> +
>>      g_free(dinfo->id);
>>      QTAILQ_REMOVE(&drives, dinfo, next);
>>      g_free(dinfo->serial);
>> @@ -307,6 +317,7 @@ static DriveInfo *blockdev_init(const char *file, QDict 
>> *bs_opts,
>>      int ro = 0;
>>      int bdrv_flags = 0;
>>      int on_read_error, on_write_error;
>> +    BlockBackend *blk;
>>      BlockDriverState *bs;
>>      DriveInfo *dinfo;
>>      ThrottleConfig cfg;
>> @@ -463,9 +474,13 @@ static DriveInfo *blockdev_init(const char *file, QDict 
>> *bs_opts,
>>      }
>
>>      const char *fmt1 = NULL, *fmt2 = NULL, *cache, *filename1, *filename2;
>> +    BlockBackend *blk1, *blk2;
>>      BlockDriverState *bs1, *bs2;
>>      int64_t total_sectors1, total_sectors2;
>>      uint8_t *buf1 = NULL, *buf2 = NULL;
>> @@ -1011,18 +1022,20 @@ static int img_compare(int argc, char **argv)
>>          goto out3;
>>      }
>>  
>> +    blk1 = blk_new("image 1", &error_abort);
>>      bs1 = bdrv_new_open("image 1", filename1, fmt1, flags, true, quiet);
>>      if (!bs1) {
>>          error_report("Can't open file %s", filename1);
>>          ret = 2;
>> -        goto out3;
>> +        goto out2;
>
> Here we allocate blk1 and bs1 an if bs1 is null (error) we jump to
> out2 which is:
>
>>  out2:
>>      bdrv_unref(bs1);
>> +    blk_unref(blk1);
>
> It's a bit strange that we will bdrv_unref(NULL) in this case.
>
> This goto chain seems odd.

You can solve the "on error, destroy the things already created" problem
like this:

    Foo *foo;
    Bar *bar;
    Baz *baz;
    [...]
    foo = new_foo();
    if (!foo) {
        goto out_foo;
    }
    bar = new_bar();
    if (!bar) {
        goto out_bar;
    }
    baz = new_baz();
    if (!baz) {
        goto out_baz;
    }
    [...]
out_baz:
    del_baz(baz);
out_bar:
    del_bar(bar);
out_foo:
    del_foo(foo);

Works, but keeping track of where exactly to go to is somewhat tedious
and error prone.

If the del_ functions do nothing for null arguments, the following also
works:

    Foo *foo = NULL;
    Bar *bar = NULL;
    Baz *baz = NULL;
    [...]
    foo = new_foo();
    if (!foo) {
        goto out;
    }
    bar = new_bar();
    if (!bar) {
        goto out;
    }
    baz = new_baz();
    if (!baz) {
        goto out;
    }
    [...]
out:
    del_baz(baz);
    del_bar(bar);
    del_foo(foo);

Simpler.  This is the reason why free(NULL) does nothing.

>>      }
>>  
>> +    blk2 = blk_new("image 2", &error_abort);
>>      bs2 = bdrv_new_open("image 2", filename2, fmt2, flags, true, quiet);
>>      if (!bs2) {
>>          error_report("Can't open file %s", filename2);
>>          ret = 2;
>> -        goto out2;
>> +        goto out1;
>>      }
>>  
>>      buf1 = qemu_blockalign(bs1, IO_BUF_SIZE);
>> @@ -1183,11 +1196,14 @@ static int img_compare(int argc, char **argv)
>>      ret = 0;
>>  
>>  out:
>> -    bdrv_unref(bs2);
>>      qemu_vfree(buf1);
>>      qemu_vfree(buf2);
>> +out1:
>> +    bdrv_unref(bs2);
>> +    blk_unref(blk2);
>>  out2:
>>      bdrv_unref(bs1);
>> +    blk_unref(blk1);
>>  out3:
>>      qemu_progress_end();
>>      return ret;
>> @@ -1200,6 +1216,7 @@ static int img_convert(int argc, char **argv)
>>      int progress = 0, flags, src_flags;
>>      const char *fmt, *out_fmt, *cache, *src_cache, *out_baseimg, 
>> *out_filename;
>>      BlockDriver *drv, *proto_drv;
>> +    BlockBackend **blk = NULL, *out_blk = NULL;
>
> Should blk be blks or blkes ? They are multiple.

I follow the bs precedence (next line).

In general, I feel using plural for array names doesn't work so well,
because most uses tend to be subscripted, and there plural feels
awkward.

>>      BlockDriverState **bs = NULL, *out_bs = NULL;
>>      int64_t total_sectors, nb_sectors, sector_num, bs_offset;
>>      int64_t *bs_sectors = NULL;
[...]



reply via email to

[Prev in Thread] Current Thread [Next in Thread]