qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
To: John Snow <jsnow@redhat.com>,
	"qemu-devel@nongnu.org" <qemu-devel@nongnu.org>,
	"qemu-block@nongnu.org" <qemu-block@nongnu.org>
Cc: Stefan Hajnoczi <stefanha@redhat.com>,
	Eric Blake <eblake@redhat.com>, Max Reitz <mreitz@redhat.com>,
	"Dr. David Alan Gilbert" <dgilbert@redhat.com>,
	Kevin Wolf <kwolf@redhat.com>,
	Juan Quintela <quintela@redhat.com>, Fam Zheng <fam@euphon.net>,
	Markus Armbruster <armbru@redhat.com>
Subject: Re: [Qemu-devel] [PATCH v2 4/4] block/dirty-bitmaps: implement inconsistent bit
Date: Thu, 28 Feb 2019 10:21:13 +0000	[thread overview]
Message-ID: <13ed7c02-3a2a-a3c6-f66c-2e4a30aef175@virtuozzo.com> (raw)
In-Reply-To: <1747ac32-4862-020d-509e-8ea655ab1771@redhat.com>

28.02.2019 2:48, John Snow wrote:
> 
> 
> On 2/25/19 11:21 AM, Vladimir Sementsov-Ogievskiy wrote:
>> 23.02.2019 3:22, John Snow wrote:
>>> Set the inconsistent bit on load instead of rejecting such bitmaps.
>>> There is no way to un-set it; the only option is to delete it.
>>>
>>> Obvervations:
>>> - bitmap loading does not need to update the header for in_use bitmaps.
>>> - inconsistent bitmaps don't need to have their data loaded; they're
>>>     glorified corruption sentinels.
>>> - bitmap saving does not need to save inconsistent bitmaps back to disk.
>>> - bitmap reopening DOES need to drop the readonly flag from inconsistent
>>>     bitmaps to allow reopening of qcow2 files with non-qemu-owned bitmaps
>>>     being eventually flushed back to disk.
>>>
>>> Signed-off-by: John Snow <jsnow@redhat.com>
>>> ---
>>>    block/qcow2-bitmap.c | 77 +++++++++++++++++++++++---------------------
>>>    1 file changed, 40 insertions(+), 37 deletions(-)
>>>
>>> diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
>>> index 3ee524da4b..d1cc11da88 100644
>>> --- a/block/qcow2-bitmap.c
>>> +++ b/block/qcow2-bitmap.c
>>> @@ -343,9 +343,15 @@ static BdrvDirtyBitmap *load_bitmap(BlockDriverState *bs,
>>>        uint32_t granularity;
>>>        BdrvDirtyBitmap *bitmap = NULL;
>>>    
>>> +    granularity = 1U << bm->granularity_bits;
>>> +    bitmap = bdrv_create_dirty_bitmap(bs, granularity, bm->name, errp);
>>> +    if (bitmap == NULL) {
>>> +        goto fail;
>>> +    }
>>> +
>>>        if (bm->flags & BME_FLAG_IN_USE) {
>>> -        error_setg(errp, "Bitmap '%s' is in use", bm->name);
>>> -        goto fail;
>>> +        /* Data is unusable, skip loading it */
>>> +        return bitmap;
>>>        }
>>>    
>>>        ret = bitmap_table_load(bs, &bm->table, &bitmap_table);
>>> @@ -356,12 +362,6 @@ static BdrvDirtyBitmap *load_bitmap(BlockDriverState *bs,
>>>            goto fail;
>>>        }
>>>    
>>> -    granularity = 1U << bm->granularity_bits;
>>> -    bitmap = bdrv_create_dirty_bitmap(bs, granularity, bm->name, errp);
>>> -    if (bitmap == NULL) {
>>> -        goto fail;
>>> -    }
>>> -
>>>        ret = load_bitmap_data(bs, bitmap_table, bm->table.size, bitmap);
>>>        if (ret < 0) {
>>>            error_setg_errno(errp, -ret, "Could not read bitmap '%s' from image",
>>> @@ -949,6 +949,7 @@ bool qcow2_load_dirty_bitmaps(BlockDriverState *bs, Error **errp)
>>>        Qcow2Bitmap *bm;
>>>        GSList *created_dirty_bitmaps = NULL;
>>>        bool header_updated = false;
>>> +    bool needs_update = false;
>>>    
>>>        if (s->nb_bitmaps == 0) {
>>>            /* No bitmaps - nothing to do */
>>> @@ -962,23 +963,27 @@ bool qcow2_load_dirty_bitmaps(BlockDriverState *bs, Error **errp)
>>>        }
>>>    
>>>        QSIMPLEQ_FOREACH(bm, bm_list, entry) {
>>> -        if (!(bm->flags & BME_FLAG_IN_USE)) {
>>> -            BdrvDirtyBitmap *bitmap = load_bitmap(bs, bm, errp);
>>> -            if (bitmap == NULL) {
>>> -                goto fail;
>>> -            }
>>> +        BdrvDirtyBitmap *bitmap = load_bitmap(bs, bm, errp);
>>> +        if (bitmap == NULL) {
>>> +            goto fail;
>>> +        }
>>>    
>>> -            if (!(bm->flags & BME_FLAG_AUTO)) {
>>> -                bdrv_disable_dirty_bitmap(bitmap);
>>> -            }
>>> -            bdrv_dirty_bitmap_set_persistance(bitmap, true);
>>> +        if (bm->flags & BME_FLAG_IN_USE) {
>>> +            bdrv_dirty_bitmap_set_inconsistent(bitmap);
>>> +        } else {
>>> +            /* NB: updated flags only get written if can_write(bs) is true. */
>>>                bm->flags |= BME_FLAG_IN_USE;
>>> -            created_dirty_bitmaps =
>>> -                    g_slist_append(created_dirty_bitmaps, bitmap);
>>> +            needs_update = true;
>>>            }
>>> +        if (!(bm->flags & BME_FLAG_AUTO)) {
>>> +            bdrv_disable_dirty_bitmap(bitmap);
>>> +        }
>>> +        bdrv_dirty_bitmap_set_persistance(bitmap, true);
>>
>> We define persistent bitmaps as which we are going to store.. But we are
>> not going to store inconsistent bitmaps. So inconsistent bitmaps are not persistent.
>>
> 
> I changed the wording for v3.
> 
>>> +        created_dirty_bitmaps =
>>> +            g_slist_append(created_dirty_bitmaps, bitmap);
>>>        }
>>>    
>>> -    if (created_dirty_bitmaps != NULL) {
>>> +    if (needs_update) {
>>
>> created_dirty_bitmaps list needed only for setting them readonly, if failed write that
>> they are IN_USE. So, instead of creating additional variable, better is just not include
>> IN_USE bitmaps to this list. And it may be renamed like set_in_use_list.
>>
> 
> If I don't add them to the list, then one of the bitmaps in the list
> fails, I don't know which bitmap to remove when we go to the error exit.


Oops, you are right.

> 
>>>            if (can_write(bs)) {
>>>                /* in_use flags must be updated */
>>>                int ret = update_ext_header_and_dir_in_place(bs, bm_list);
>>> @@ -1112,23 +1117,21 @@ int qcow2_reopen_bitmaps_rw_hint(BlockDriverState *bs, bool *header_updated,
>>>        }
>>>    
>>>        QSIMPLEQ_FOREACH(bm, bm_list, entry) {
>>> -        if (!(bm->flags & BME_FLAG_IN_USE)) {
>>> -            BdrvDirtyBitmap *bitmap = bdrv_find_dirty_bitmap(bs, bm->name);
>>> -            if (bitmap == NULL) {
>>> -                continue;
>>> -            }
>>> -
>>> -            if (!bdrv_dirty_bitmap_readonly(bitmap)) {
>>> -                error_setg(errp, "Bitmap %s is not readonly but not marked"
>>> -                                 "'IN_USE' in the image. Something went wrong,"
>>> -                                 "all the bitmaps may be corrupted", bm->name);
>>> -                ret = -EINVAL;
>>> -                goto out;
>>> -            }
>>> +        BdrvDirtyBitmap *bitmap = bdrv_find_dirty_bitmap(bs, bm->name);
>>> +        if (bitmap == NULL) {
>>> +            continue;
>>> +        }
>>
>>>    
>>> -            bm->flags |= BME_FLAG_IN_USE;
>>> -            ro_dirty_bitmaps = g_slist_append(ro_dirty_bitmaps, bitmap);
>>> +        if (!bdrv_dirty_bitmap_readonly(bitmap)) {
>>
>> so, we'll fail, as we didn't marked inconsistetn bitmaps as readonly above. Should we?
>> Or we may check here inconsistance directly.
>>
> 
> OH! I didn't mean to do this -- I want to mark all inconsistent bitmaps
> as readonly, yes. I will fix this.
> 
>>> +            error_setg(errp, "Bitmap %s was loaded prior to rw-reopen, but was "
>>> +                       "not marked as readonly. This is a bug, something went "
>>> +                       "wrong. All of the bitmaps may be corrupted", bm->name);
>>
>> Hmm, your wording covers invalid case when inconsistent bitmap is not IN_USE, and sounds
>> better for user, though may be less precise (as it may be not one reopen in a sequence..).
>> Ok for me.
>>
> 
> With all inconsistent bitmaps marked as readonly, this shouldn't ever
> actually trigger. All persistent bitmaps on a drive that hits
> reopen_rw_hint ought to be readonly, right?

not necessary I think. Some bitmaps may be created through qmp command, they will not be readonly,
as they are not flushed to storage.

But it of course doesn't lead to that message. Yes it should never happen I think, so it is worded in
manner "This is a bug". On the other hand, assume that someone illegally modifies image, while
Qemu is running and clear IN_USE bit. In this case we'll see that message.

> 
> That's my assumption; that we should never see this message.
> 
>>> +            ret = -EINVAL;
>>> +            goto out;
>>>            }
>>> +
>>> +        bm->flags |= BME_FLAG_IN_USE;
>>> +        ro_dirty_bitmaps = g_slist_append(ro_dirty_bitmaps, bitmap);
>>>        }
>>>    
>>>        if (ro_dirty_bitmaps != NULL) {
>>> @@ -1424,8 +1427,8 @@ void qcow2_store_persistent_dirty_bitmaps(BlockDriverState *bs, Error **errp)
>>>            Qcow2Bitmap *bm;
>>>    
>>>            if (!bdrv_dirty_bitmap_get_persistance(bitmap) ||
>>> -            bdrv_dirty_bitmap_readonly(bitmap))
>>> -        {
>>> +            bdrv_dirty_bitmap_readonly(bitmap) ||
>>> +            bdrv_dirty_bitmap_inconsistent(bitmap)) {
>>>                continue;
>>>            }
>>>    
>>>
>>
>>
> 
> Sending a V3 for further critique, but freeze is soon.
> 


-- 
Best regards,
Vladimir

      reply	other threads:[~2019-02-28 10:21 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-02-23  0:22 [Qemu-devel] [PATCH v2 0/4] bitmaps: add inconsistent bit John Snow
2019-02-23  0:22 ` [Qemu-devel] [PATCH v2 1/4] block/dirty-bitmaps: " John Snow
2019-02-25 13:47   ` Eric Blake
2019-02-25 14:18   ` Vladimir Sementsov-Ogievskiy
2019-02-25 15:30     ` Vladimir Sementsov-Ogievskiy
2019-02-27 18:45       ` John Snow
2019-02-28 10:13         ` Vladimir Sementsov-Ogievskiy
2019-02-28 13:44           ` Eric Blake
2019-02-28 14:01             ` Vladimir Sementsov-Ogievskiy
2019-02-25 18:32     ` John Snow
2019-02-25 15:51   ` [Qemu-devel] [PATCH] dirty-bitmap: introduce inconsistent bitmaps Vladimir Sementsov-Ogievskiy
2019-02-23  0:22 ` [Qemu-devel] [PATCH v2 2/4] block/dirty-bitmap: add inconsistent status John Snow
2019-02-25 15:12   ` Eric Blake
2019-02-23  0:22 ` [Qemu-devel] [PATCH v2 3/4] block/dirty-bitmaps: add block_dirty_bitmap_check function John Snow
2019-02-25 13:37   ` Vladimir Sementsov-Ogievskiy
2019-02-25 14:59     ` Vladimir Sementsov-Ogievskiy
2019-02-25 15:07       ` Eric Blake
2019-02-25 15:11         ` Vladimir Sementsov-Ogievskiy
2019-02-25 21:22       ` John Snow
2019-02-23  0:22 ` [Qemu-devel] [PATCH v2 4/4] block/dirty-bitmaps: implement inconsistent bit John Snow
2019-02-25 16:21   ` Vladimir Sementsov-Ogievskiy
2019-02-27 23:48     ` John Snow
2019-02-28 10:21       ` Vladimir Sementsov-Ogievskiy [this message]

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=13ed7c02-3a2a-a3c6-f66c-2e4a30aef175@virtuozzo.com \
    --to=vsementsov@virtuozzo.com \
    --cc=armbru@redhat.com \
    --cc=dgilbert@redhat.com \
    --cc=eblake@redhat.com \
    --cc=fam@euphon.net \
    --cc=jsnow@redhat.com \
    --cc=kwolf@redhat.com \
    --cc=mreitz@redhat.com \
    --cc=qemu-block@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    --cc=quintela@redhat.com \
    --cc=stefanha@redhat.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).