qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Wenchao Xia <xiawenc@linux.vnet.ibm.com>
To: Eric Blake <eblake@redhat.com>
Cc: kwolf@redhat.com, phrdina@redhat.com, armbru@redhat.com,
	qemu-devel@nongnu.org, lcapitulino@redhat.com,
	stefanha@gmail.com, pbonzini@redhat.com
Subject: Re: [Qemu-devel] [PATCH 4/7] block: distinguish id and name in bdrv_find_snapshot()
Date: Thu, 02 May 2013 10:02:27 +0800	[thread overview]
Message-ID: <5181C933.2050708@linux.vnet.ibm.com> (raw)
In-Reply-To: <51800A98.4040005@redhat.com>

于 2013-5-1 2:16, Eric Blake 写道:
> On 04/26/2013 03:31 AM, Wenchao Xia wrote:
>> To make it clear about id and name in searching, the API is changed
>> a bit to distinguish them, and caller can choose to search by id or name.
>> If not found, *errp will be set to tip why.
>>
>> Note that the caller logic is changed a bit:
>> 1) In del_existing_snapshots() called by do_savevm(), it travers twice
>> to find the snapshot, instead once, so matching sequence may change
>> if there are unwisely chosen, mixed id and names.
>> 2) In do_savevm(), same with del_existing_snapshot(), when it tries to
>> find the snapshot to overwrite, matching sequence may change for same
>> reason.
>> 3) In load_vmstate(), first when it tries to find the snapshot to be loaded,
>> sequence may change for the same reason of above. Later in validation, the
>> logic is changed to be more strict to require both id and name matching.
>> 4) In do_info_snapshot(), in validation, the logic is changed to be more
>> strict to require both id and name matching.
>>
>> Savevm, loadvm logic may need to be improved later, to avoid mixing of them.
>>
>> Some code is borrowed from Pavel's patch.
>>
>> Signed-off-by: Wenchao Xia <xiawenc@linux.vnet.ibm.com>
>> Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
>> ---
>>   block/snapshot.c         |   72 +++++++++++++++++++++++++++++++++++++++-------
>>   include/block/snapshot.h |    5 ++-
>>   savevm.c                 |   35 ++++++++++++----------
>>   3 files changed, 83 insertions(+), 29 deletions(-)
>
>> + *
>> + * Returns: true when a snapshot is found and @sn_info will be filled, false
>> + * when error or not found with @errp filled if errp != NULL.
>> + */
>> +bool bdrv_snapshot_find(BlockDriverState *bs, QEMUSnapshotInfo *sn_info,
>> +                        const char *id, const char *name, Error **errp)
>
> Unusual convention to have (input, output, input, input, output)
> parameters; as long as you are changing the signature, I'd consider
> putting all input parameters (bs, id, name) firs, then output parameters
> last (sn_info, errp).
>
>>   {
>>       QEMUSnapshotInfo *sn_tab, *sn;
>> -    int nb_sns, i, ret;
>> +    int nb_sns, i;
>> +    bool ret = false;
>>
>> -    ret = -ENOENT;
>>       nb_sns = bdrv_snapshot_list(bs, &sn_tab);
>>       if (nb_sns < 0) {
>> -        return ret;
>> +        error_setg_errno(errp, -nb_sns, "Failed to get a snapshot list");
>> +        return false;
>> +    } else if (nb_sns == 0) {
>> +        error_setg(errp, "Device has no snapshots");
>> +        return false;
>>       }
>> -    for (i = 0; i < nb_sns; i++) {
>> -        sn = &sn_tab[i];
>> -        if (!strcmp(sn->id_str, name) || !strcmp(sn->name, name)) {
>> -            *sn_info = *sn;
>> -            ret = 0;
>> -            break;
>> +
>
> No assertion that at least one of id or name is provided,...
>
>> +
>> +    if (id && name) {
>> +        for (i = 0; i < nb_sns; i++) {
>> +            sn = &sn_tab[i];
>> +            if (!strcmp(sn->id_str, id) && !strcmp(sn->name, name)) {
>> +                *sn_info = *sn;
>> +                ret = true;
>> +                break;
>> +            }
>> +        }
>> +    } else if (id) {
>> +        for (i = 0; i < nb_sns; i++) {
>> +            sn = &sn_tab[i];
>> +            if (!strcmp(sn->id_str, id)) {
>> +                *sn_info = *sn;
>> +                ret = true;
>> +                break;
>> +            }
>> +        }
>> +    } else if (name) {
>> +        for (i = 0; i < nb_sns; i++) {
>> +            sn = &sn_tab[i];
>> +            if (!strcmp(sn->name, name)) {
>> +                *sn_info = *sn;
>> +                ret = true;
>> +                break;
>> +            }
>>           }
>>       }
>> +
>> +    if (!ret) {
>> +        error_setg(errp, "Device have no matching snapshot");
>> +    }
>
> ...therefore, if I call bdrv_snapshot_find(bs, &info, NULL, NULL, errp),
> I'll get this error.  Seems okay.
>
>> +++ b/savevm.c
>> @@ -2286,8 +2286,8 @@ static int del_existing_snapshots(Monitor *mon, const char *name)
>>       bs = NULL;
>>       while ((bs = bdrv_next(bs))) {
>>           if (bdrv_can_snapshot(bs) &&
>> -            bdrv_snapshot_find(bs, snapshot, name) >= 0)
>> -        {
>> +            (bdrv_snapshot_find(bs, snapshot, name, NULL, NULL) ||
>> +             bdrv_snapshot_find(bs, snapshot, NULL, name, NULL))) {
>
> This does an id lookup first, and falls back to a name lookup.  Is that
> what we want?  Consider an image with the following snapshots:
>
> id 1 name 2
> id 2 name 3
> id 3 name 1
> id 4 name 5
>
> Pre-patch, find(1) gives id 1, find(2) gives id 1, find(3) gives id 2,
> find(4) gives id 4, find(5) gives id 4; no way to get id 3.  Post-patch,
> find(1,NULL) gives id 1, find(2,NULL) gives id 2, find(3,NULL) gives id
> 3, find(4,NULL) gives id 4, find(5,NULL) fails and you fall back to
> find(NULL,5) to give id 4.  Thus, it only makes a difference for
> snapshots whose name is a numeric string that also matches an id, where
> your change now favors the id lookup over the entire set instead of the
> first name or id match while doing a single pass over the set.
>
> Pavel's series on top of this would change the code to favor a name-only
> lookup, or an explicit HMP option to do an id-only lookup, instead of
> this code's double lookup.
>
> At this point, I'm okay with the semantics of this patch (especially
> since we may be cleaning it up further in Pavel's patch series), but it
> deserves explicit documentation in the commit message on what semantics
> are changing (favoring id more strongly) and why (so that we can select
> all possible snapshots, instead of being unable to select snapshots
> whose id was claimed as a name of an earlier snapshot).
>
   To avoid trouble, I think a new function named
bdrv_snapshot_find_by_id_and_name() is better. Later Pavel
can directly call this new function, and after that we can
delete original bdrv_snapshot_find(). Pavel, what do you
think?

>> @@ -2437,12 +2437,14 @@ int load_vmstate(const char *name)
>> @@ -2461,11 +2463,11 @@ int load_vmstate(const char *name)
>>               return -ENOTSUP;
>>           }
>>
>> -        ret = bdrv_snapshot_find(bs, &sn, name);
>> -        if (ret < 0) {
>> +        /* vm snapshot will always have same id and name, check do_savevm(). */
>> +        if (!bdrv_snapshot_find(bs, &sn, sn.id_str, sn.name, NULL)) {
>>               error_report("Device '%s' does not have the requested snapshot '%s'",
>>                              bdrv_get_device_name(bs), name);
>> -            return ret;
>> +            return -ENOENT;
>>           }
>
> Are we 100% sure that a given snapshot name has the same id across all
> block devices?  Or is it possible to have:
>
> disk a: [id 1 name A, id 2 name B]
> disk b: [id 1 name B]
>
> where it is possible to load snapshot [B] and get consistent state?  If
> it is possible to have non-matched ids across same-name snapshots, then
> looking up by requiring a match of both id and name will fail, whereas
> the pre-patch code would succeed.
>
   not possible, I checked the existing code, a loadable snapshot, that
is the one with vmstate, will always have same id and name, see savevm
logic and qcow2's snapshot creation code.
   What changes is: previous, in "info snapshot", it will try show some
snapshot that may have the situation you described above, which may be
brought by qemu-img or hotplug operation, and which can't be loaded in
"loadvm". Now it will be filtered out.
   Maybe there are more complicated case, but I think let management
stack handling it, is a better option.


>>       }
>>
>> @@ -2536,7 +2538,7 @@ void do_info_snapshots(Monitor *mon, const QDict *qdict)
>>   {
>>       BlockDriverState *bs, *bs1;
>>       QEMUSnapshotInfo *sn_tab, *sn, s, *sn_info = &s;
>> -    int nb_sns, i, ret, available;
>> +    int nb_sns, i, available;
>>       int total;
>>       int *available_snapshots;
>>       char buf[256];
>> @@ -2567,8 +2569,9 @@ void do_info_snapshots(Monitor *mon, const QDict *qdict)
>>
>>           while ((bs1 = bdrv_next(bs1))) {
>>               if (bdrv_can_snapshot(bs1) && bs1 != bs) {
>> -                ret = bdrv_snapshot_find(bs1, sn_info, sn->id_str);
>> -                if (ret < 0) {
>> +                /* vm snapshot will always have same id and name */
>> +                if (!bdrv_snapshot_find(bs1, sn_info,
>> +                                        sn->id_str, sn->name, NULL)) {
>
> Again, is this true, or are you needlessly filtering out snapshots that
> have a consistent name but non-matching ids?
>


-- 
Best Regards

Wenchao Xia

  reply	other threads:[~2013-05-02  2:03 UTC|newest]

Thread overview: 34+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-04-26  9:31 [Qemu-devel] [PATCH 0/7] qapi and snapshot code clean up in block layer Wenchao Xia
2013-04-26  9:31 ` [Qemu-devel] [PATCH 1/7] block: drop bs_snapshots global variable Wenchao Xia
2013-04-26  9:31 ` [Qemu-devel] [PATCH 2/7] block: move bdrv_snapshot_find() to block/snapshot.c Wenchao Xia
2013-04-26  9:31 ` [Qemu-devel] [PATCH 3/7] block: move snapshot code in block.c " Wenchao Xia
2013-04-26 19:05   ` Eric Blake
2013-04-26  9:31 ` [Qemu-devel] [PATCH 4/7] block: distinguish id and name in bdrv_find_snapshot() Wenchao Xia
2013-04-26 14:34   ` Stefan Hajnoczi
2013-04-26 14:47     ` Eric Blake
2013-04-27  3:34     ` Wenchao Xia
2013-04-30 17:52       ` Eric Blake
2013-04-30 18:16   ` Eric Blake
2013-05-02  2:02     ` Wenchao Xia [this message]
2013-05-02 21:12       ` Pavel Hrdina
2013-04-26  9:31 ` [Qemu-devel] [PATCH 5/7] block: move collect_snapshots() and collect_image_info() to block/qapi.c Wenchao Xia
2013-04-26  9:31 ` [Qemu-devel] [PATCH 6/7] block: move qmp and info dump related code " Wenchao Xia
2013-04-30 17:50   ` Eric Blake
2013-04-26  9:31 ` [Qemu-devel] [PATCH 7/7] block: dump to monitor for bdrv_snapshot_dump() and bdrv_image_info_dump() Wenchao Xia
2013-04-26 14:46   ` Stefan Hajnoczi
2013-04-27  3:37     ` Wenchao Xia
2013-04-29 19:05     ` Luiz Capitulino
2013-05-02  2:05       ` Wenchao Xia
2013-05-02 12:02         ` Luiz Capitulino
2013-05-03  2:51           ` Wenchao Xia
2013-05-06  2:09             ` Wenchao Xia
2013-05-06 13:22               ` Luiz Capitulino
2013-05-15  2:10                 ` Wenchao Xia
2013-05-15 12:28                   ` Luiz Capitulino
2013-05-16  2:22                     ` Wenchao Xia
2013-05-16 12:17                       ` Luiz Capitulino
2013-05-17  3:30                         ` Wenchao Xia
2013-05-17 12:30                           ` Luiz Capitulino
2013-05-20  2:39                             ` Wenchao Xia
2013-05-22  2:09                               ` Wenchao Xia
2013-05-22 12:23                                 ` Luiz Capitulino

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=5181C933.2050708@linux.vnet.ibm.com \
    --to=xiawenc@linux.vnet.ibm.com \
    --cc=armbru@redhat.com \
    --cc=eblake@redhat.com \
    --cc=kwolf@redhat.com \
    --cc=lcapitulino@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=phrdina@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=stefanha@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).