All of lore.kernel.org
 help / color / mirror / Atom feed
From: Max Reitz <mreitz@redhat.com>
To: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>,
	qemu-block@nongnu.org, qemu-devel@nongnu.org
Cc: kwolf@redhat.com, armbru@redhat.com, eblake@redhat.com,
	jsnow@redhat.com, famz@redhat.com, den@openvz.org,
	stefanha@redhat.com, pbonzini@redhat.com
Subject: Re: [Qemu-devel] [PATCH 07/22] qcow2-bitmap: introduce auto-loading bitmaps
Date: Sat, 1 Oct 2016 18:26:20 +0200	[thread overview]
Message-ID: <93be46ce-5b73-c7d3-ada0-d59461227dbf@redhat.com> (raw)
In-Reply-To: <1475232808-4852-8-git-send-email-vsementsov@virtuozzo.com>

[-- Attachment #1: Type: text/plain, Size: 19510 bytes --]

On 30.09.2016 12:53, Vladimir Sementsov-Ogievskiy wrote:
> Auto loading bitmaps are bitmaps in Qcow2, with AUTO flag set. They are

*with the AUTO flag set

> loaded at image open and becomes BdrvDirtyBitmap's for corresponding

"loaded when the image is opened and become BdrvDirtyBitmaps for the
corresponding drive."

> drive. These bitmaps are deleted from Qcow2 image after loading to avoid

*from the Qcow2 image

> conflicts.
> 
> Extra data in bitmaps is not supported for now.
> 
> Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
> ---
>  block/qcow2-bitmap.c | 518 ++++++++++++++++++++++++++++++++++++++++++++++++++-
>  block/qcow2.c        |   5 +
>  block/qcow2.h        |   3 +
>  3 files changed, 525 insertions(+), 1 deletion(-)
> 
> diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
> index cd18b07..760a047 100644
> --- a/block/qcow2-bitmap.c
> +++ b/block/qcow2-bitmap.c
> @@ -25,6 +25,12 @@

[...]

> +static void clear_bitmap_table(BlockDriverState *bs, uint64_t *bitmap_table,
> +                               uint32_t bitmap_table_size)
> +{
> +    BDRVQcow2State *s = bs->opaque;
> +    int cl_size = s->cluster_size;
> +    int i;
> +
> +    for (i = 0; i < bitmap_table_size; ++i) {
> +        uint64_t addr = bitmap_table[i];
> +        if (addr <= 1) {

I'd rather add a BME_TABLE_ENTRY_OFFSET_MASK
(0x00fffffffffffe00ull) and then use:

uint64_t addr = bitmap_table[i] & BME_TABLE_ENTRY_OFFSET_MASK;
if (!addr) {

> +            continue;
> +        }
> +
> +        qcow2_free_clusters(bs, addr, cl_size, QCOW2_DISCARD_ALWAYS);

I think this should rather be QCOW2_DISCARD_OTHER; or you introduce a
new QCOW2_DISCARD_* flag.

(The same applies to all the other QCOW2_DISCARD_ALWAYS users here.)

Also, I don't really see the point of introducing cl_size just for this
place; it doesn't even save you from a line wrap.

> +        bitmap_table[i] = 0;
> +    }
> +}
> +
> +static int bitmap_table_load(BlockDriverState *bs, Qcow2BitmapDirEntry *entry,
> +                             uint64_t **table)
> +{
> +    int ret;
> +
> +    *table = g_try_new(uint64_t, entry->bitmap_table_size);
> +    if (*table == NULL) {

Not that g_try_new() will return NULL if you try to allocate a buffer
with size 0.

Normally, entry->bitmap_table_size shouldn't be 0, but I don't think
you're catching that case anywhere.

> +        return -ENOMEM;
> +    }
> +

I wouldn't mind an

assert(entry->bitmap_table_size <= UINT32_MAX / sizeof(uint64_t));

here because of the following multiplication (which is extended to 64
bit on 64 bit machines, but stays in 32 bit on 32 bit machines).

(Of course,

assert(entry->bitmap_table_size <= BME_MAX_TABLE_SIZE);

would be fine, too.)

> +    ret = bdrv_pread(bs->file, entry->bitmap_table_offset,
> +                     *table, entry->bitmap_table_size * sizeof(uint64_t));
> +    if (ret < 0) {
> +        g_free(*table);
> +        *table = NULL;
> +        return ret;
> +    }
> +
> +    bitmap_table_to_cpu(*table, entry->bitmap_table_size);
> +
> +    return 0;
> +}
> +
> +static void do_free_bitmap_clusters(BlockDriverState *bs,
> +                                    uint64_t table_offset,
> +                                    uint32_t table_size,
> +                                    uint64_t *bitmap_table)
> +{
> +    clear_bitmap_table(bs, bitmap_table, table_size);
> +
> +    qcow2_free_clusters(bs, table_offset, table_size * sizeof(uint64_t),
> +                        QCOW2_DISCARD_ALWAYS);
> +}
> +
> +static int free_bitmap_clusters(BlockDriverState *bs, Qcow2BitmapDirEntry *entry)
> +{
> +    int ret;
> +    uint64_t *bitmap_table;
> +
> +    ret = bitmap_table_load(bs, entry, &bitmap_table);
> +    if (ret < 0 || bitmap_table == NULL) {

That should be:

if (ret < 0) {
    assert(bitmap_table == NULL);

Or the other way around:

if (bitmap_table == NULL) {
    assert(ret < 0);

Otherwise, it looks like bitmap_table may be NULL with ret being 0, and
the next statement would make this function return success even though
it actually failed.

> +        return ret;
> +    }
> +
> +    do_free_bitmap_clusters(bs, entry->bitmap_table_offset,
> +                            entry->bitmap_table_size, bitmap_table);
> +
> +    return 0;

You're leaking bitmap_table here.

> +}
> +
> +/* dirty sectors in cluster is a number of sectors in the image, corresponding
> + * to one cluster of bitmap data */

How about:

This function returns the number of sectors covered by a single cluster
of dirty bitmap data.

> +static uint64_t dirty_sectors_in_cluster(const BDRVQcow2State *s,
> +                                         const BdrvDirtyBitmap *bitmap)
> +{
> +    uint32_t sector_granularity =
> +            bdrv_dirty_bitmap_granularity(bitmap) >> BDRV_SECTOR_BITS;
> +
> +    return (uint64_t)sector_granularity * (s->cluster_size << 3);
> +}
> +
> +static int load_bitmap_data(BlockDriverState *bs,
> +                            const uint64_t *dirty_bitmap_table,
> +                            uint32_t dirty_bitmap_table_size,
> +                            BdrvDirtyBitmap *bitmap)
> +{
> +    int ret = 0;
> +    BDRVQcow2State *s = bs->opaque;
> +    uint64_t sector, dsc;
> +    uint64_t bm_size = bdrv_dirty_bitmap_size(bitmap);
> +    int cl_size = s->cluster_size;

Once more, I don't really see the reason to put this into a dedicated
variable (I feel like it makes the code harder to read because you have
to keep in mind what cl_size is).

> +    uint8_t *buf = NULL;
> +    uint32_t i, tab_size =
> +            size_to_clusters(s,
> +                bdrv_dirty_bitmap_serialization_size(bitmap, 0, bm_size));
> +
> +    if (tab_size != dirty_bitmap_table_size) {
> +        return -EINVAL;
> +    }

You should also check that tab_size does not exceed BME_MAX_TABLE_SIZE.

And maybe you should check that the physical size of the bitmap data
does not exceed BME_MAX_PHYS_SIZE, but I'm not so sure why you have that
constant at all because it's basically superseded by the existence of
BME_MAX_TABLE_SIZE.

> +
> +    bdrv_clear_dirty_bitmap(bitmap, NULL);
> +
> +    buf = g_malloc0(cl_size);

g_malloc() would suffice as well, since you'll be overwriting all of it
anyway.

> +    dsc = dirty_sectors_in_cluster(s, bitmap);
> +    for (i = 0, sector = 0; i < tab_size; ++i, sector += dsc) {
> +        uint64_t end = MIN(bm_size, sector + dsc);
> +        uint64_t offset = dirty_bitmap_table[i];
> +
> +        if (offset == 1) {
> +            bdrv_dirty_bitmap_deserialize_ones(bitmap, sector, end, false);
> +        } else if (offset > 1) {

As before, I'd organize this differently, e.g. like:

uint64_t table_entry = dirty_bitmap_table[i];
uint64_t offset = table_entry & BME_TABLE_ENTRY_OFFSET_MASK;

if (table_entry & BME_TABLE_ENTRY_RESERVED_MASK) {
    ret = -EINVAL;
    goto finish;
}

if (!offset) {
    if (table_entry & 1) {
        bdrv_dirty_bitmap_deserialize_ones(bitmap, sector, end, false);
    } else {
        /* No need to deserialize zeroes because the dirty bitmap is
         * already cleared */
    }
} else {
    ret = bdrv_pread(...);
    ...
}

It's more code, yes, but I find it easier to read because it reflects
the specification better.

> +            ret = bdrv_pread(bs->file, offset, buf, cl_size);
> +            if (ret < 0) {
> +                goto finish;
> +            }
> +            bdrv_dirty_bitmap_deserialize_part(bitmap, buf, sector, end, false);
> +        }
> +    }
> +    ret = 0;
> +
> +    bdrv_dirty_bitmap_deserialize_finish(bitmap);
> +
> +finish:
> +    g_free(buf);
> +
> +    return ret;
> +}
> +
> +static BdrvDirtyBitmap *load_bitmap(BlockDriverState *bs,
> +                                    Qcow2BitmapDirEntry *entry, Error **errp)
> +{
> +    int ret;
> +    uint64_t *bitmap_table = NULL;
> +    uint32_t granularity;
> +    BdrvDirtyBitmap *bitmap = NULL;
> +    char *name = g_strndup(dir_entry_name_notcstr(entry), entry->name_size);

Maybe you should limit entry->name_size to BME_MAX_NAME_SIZE.

> +
> +    ret = bitmap_table_load(bs, entry, &bitmap_table);
> +    if (ret < 0) {
> +        error_setg_errno(errp, -ret,
> +                         "Could not read bitmap_table table from image");
> +        goto fail;
> +    }
> +
> +    granularity = 1U << entry->granularity_bits;

You should be making sure that entry->granularity_bits does not exceed
[BME_MIN_GRANULARITY_BITS, BME_MAX_GRANULARITY_BITS] before this point.

> +    bitmap = bdrv_create_dirty_bitmap(bs, granularity, name, errp);
> +    if (bitmap == NULL) {
> +        goto fail;
> +    }
> +
> +    ret = load_bitmap_data(bs, bitmap_table, entry->bitmap_table_size,
> +                           bitmap);
> +    if (ret < 0) {
> +        error_setg_errno(errp, -ret, "Could not read bitmap from image");
> +        goto fail;
> +    }
> +
> +    g_free(name);
> +    g_free(bitmap_table);
> +    return bitmap;
> +
> +fail:
> +    g_free(name);
> +    g_free(bitmap_table);
> +    if (bitmap != NULL) {
> +        bdrv_release_dirty_bitmap(bs, bitmap);
> +    }
> +
> +    return NULL;
> +}
> +
> +/* directory_read
> + * Read bitmaps directory from bs by @offset and @size. Convert it to cpu
> + * format from BE.
> + */
> +static uint8_t *directory_read(BlockDriverState *bs,
> +                               uint64_t offset, uint64_t size, Error **errp)
> +{
> +    int ret;
> +    uint8_t *dir, *dir_end;
> +    Qcow2BitmapDirEntry *e;

I think you should return an error if size >
QCOW_MAX_DIRTY_BITMAP_DIRECTORY_SIZE.

> +
> +    dir = g_try_malloc(size);
> +    if (dir == NULL) {
> +        error_setg(errp, "Can't allocate space for bitmap directory.");

Please drop the full stop at the end of the message.

(And I personally don't like contractions ("can't") in user-facing
messages too much, but that is just my taste.)

> +        return NULL;
> +    }
> +    dir_end = dir + size;
> +
> +    ret = bdrv_pread(bs->file, offset, dir, size);
> +    if (ret < 0) {
> +        error_setg_errno(errp, -ret, "Can't read bitmap directory.");

Again, no full stop at the end of error messages, please.

> +        goto fail;
> +    }
> +
> +    /* loop is safe because next entry offset is calculated after conversion to

Should it be s/safe/unsafe/?

> +     * cpu format */
> +    for_each_bitmap_dir_entry_unsafe(e, dir, size) {
> +        if ((uint8_t *)(e + 1) > dir_end) {
> +            goto broken_dir;
> +        }
> +
> +        bitmap_dir_entry_to_cpu(e);
> +
> +        if ((uint8_t *)next_dir_entry(e) > dir_end) {
> +            goto broken_dir;
> +        }
> +
> +        if (e->extra_data_size != 0) {
> +            error_setg(errp, "Can't load bitmap '%.*s' from '%s':"
> +                       "extra data not supported.", e->name_size,

Full stop again.

Also, I'm not quite sure why you give the device/node name here. You
don't do that anywhere else and I think if we want to emit the
information where something failed, it should be added at some previous
point in the call chain.

> +                       dir_entry_name_notcstr(e),
> +                       bdrv_get_device_or_node_name(bs));
> +            goto fail;
> +        }
> +    }

Maybe you should count the number of dirty bitmaps and return an error
if it exceeds QCOW_MAX_DIRTY_BITMAPS.

> +
> +    assert((uint8_t *)e == dir_end);

I think this should rather go to broken_dir if they're not equal.

> +
> +    return dir;
> +
> +broken_dir:
> +    error_setg(errp, "Broken bitmap directory.");

And again.

> +
> +fail:
> +    g_free(dir);
> +
> +    return NULL;
> +}
> +
> +static int update_header_sync(BlockDriverState *bs)
> +{
> +    int ret;
> +
> +    ret = qcow2_update_header(bs);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +
> +    ret = bdrv_flush(bs);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +
> +    return 0;
> +}
> +
> +/* write bitmap directory from the state to new allocated clusters */
> +static int64_t directory_write(BlockDriverState *bs, const uint8_t *dir,
> +                               size_t size)
> +{
> +    int ret = 0;
> +    uint8_t *dir_be = NULL;
> +    int64_t dir_offset = 0;
> +
> +    dir_be = g_try_malloc(size);
> +    if (dir_be == NULL) {
> +        return -ENOMEM;
> +    }
> +    memcpy(dir_be, dir, size);
> +    bitmap_directory_to_be(dir_be, size);
> +
> +    /* Allocate space for the new bitmap directory */
> +    dir_offset = qcow2_alloc_clusters(bs, size);
> +    if (dir_offset < 0) {
> +        ret = dir_offset;
> +        goto out;
> +    }
> +
> +    /* The bitmap directory position has not yet been updated, so these
> +     * clusters must indeed be completely free */
> +    ret = qcow2_pre_write_overlap_check(bs, 0, dir_offset, size);
> +    if (ret < 0) {
> +        goto out;
> +    }
> +
> +    ret = bdrv_pwrite(bs->file, dir_offset, dir_be, size);
> +    if (ret < 0) {
> +        goto out;
> +    }
> +
> +out:
> +    g_free(dir_be);
> +
> +    if (ret < 0) {
> +        if (dir_offset > 0) {
> +            qcow2_free_clusters(bs, dir_offset, size, QCOW2_DISCARD_ALWAYS);
> +        }
> +
> +        return ret;
> +    }
> +
> +    return dir_offset;
> +}
> +
> +static int directory_update(BlockDriverState *bs, uint8_t *new_dir,
> +                            size_t new_size, uint32_t new_nb_bitmaps)
> +{
> +    BDRVQcow2State *s = bs->opaque;
> +    int ret;
> +    int64_t new_offset = 0;
> +    uint64_t old_offset = s->bitmap_directory_offset;
> +    uint64_t old_size = s->bitmap_directory_size;
> +    uint32_t old_nb_bitmaps = s->nb_bitmaps;
> +    uint64_t old_autocl = s->autoclear_features;
> +
> +    if (new_size > QCOW_MAX_DIRTY_BITMAP_DIRECTORY_SIZE) {
> +        return -EINVAL;
> +    }

Also, you should probably check new_nb_bitmaps against
QCOW_MAX_DIRTY_BITMAPS, but maybe you'll be adding that check somewhere
else in a future patch. In that case, an assertion wouldn't be too bad
here, though.

> +
> +    if ((new_size == 0) != (new_nb_bitmaps == 0)) {
> +        return -EINVAL;
> +    }
> +
> +    if (new_nb_bitmaps > 0) {
> +        new_offset = directory_write(bs, new_dir, new_size);
> +        if (new_offset < 0) {
> +            return new_offset;
> +        }
> +
> +        ret = bdrv_flush(bs);
> +        if (ret < 0) {
> +            goto fail;
> +        }
> +    }
> +    s->bitmap_directory_offset = new_offset;
> +    s->bitmap_directory_size = new_size;
> +    s->nb_bitmaps = new_nb_bitmaps;
> +
> +    ret = update_header_sync(bs);
> +    if (ret < 0) {
> +        goto fail;
> +    }
> +
> +    if (old_size) {
> +        qcow2_free_clusters(bs, old_offset, old_size, QCOW2_DISCARD_ALWAYS);
> +    }
> +
> +    return 0;
> +
> +fail:
> +    if (new_offset > 0) {
> +        qcow2_free_clusters(bs, new_offset, new_size, QCOW2_DISCARD_ALWAYS);
> +        s->bitmap_directory_offset = old_offset;
> +        s->bitmap_directory_size = old_size;
> +        s->nb_bitmaps = old_nb_bitmaps;
> +        s->autoclear_features = old_autocl;

Why are you restoring the autoclear features? From a quick glance I
can't see any code path that changes this field here, and if there is
one, it probably has a good reason to do so.

> +    }
> +
> +    return ret;
> +}
> +
> +int qcow2_read_bitmaps(BlockDriverState *bs, Error **errp)
> +{
> +    int ret;
> +    BDRVQcow2State *s = bs->opaque;
> +    uint8_t *dir, *new_dir, *new_pos;
> +    uint64_t dir_size;

I suggest initializing this variable here (to s->bitmap_directory_size)...

> +    Qcow2BitmapDirEntry *e;
> +    uint32_t new_nb_bitmaps = 0;
> +
> +    if (s->nb_bitmaps == 0) {
> +        /* No bitmaps - nothing to do */
> +        return 0;
> +    }
> +
> +    new_pos = new_dir = g_try_malloc(s->bitmap_directory_size);

...and then using it here...

> +    if (new_dir == NULL) {
> +        error_setg(errp, "Can't allocate space for bitmap directory.");
> +        return -ENOMEM;
> +    }
> +
> +    dir_size = s->bitmap_directory_size;
> +    dir = directory_read(bs, s->bitmap_directory_offset,
> +                         s->bitmap_directory_size, errp);

...and here.

Alternatively, of course, you can just drop the variable and use
s->bitmap_directory_size everywhere.

> +    if (dir == NULL) {
> +        ret = -EINVAL;
> +        goto out;
> +    }
> +
> +    for_each_bitmap_dir_entry(e, dir, dir_size) {
> +        uint32_t fl = e->flags;
> +
> +        if (fl & BME_FLAG_AUTO) {
> +            BdrvDirtyBitmap *bitmap = load_bitmap(bs, e, errp);
> +            if (bitmap == NULL) {
> +                ret = -EINVAL;
> +                goto out;
> +            }
> +        } else {
> +            /* leave bitmap in the image */
> +            new_pos += copy_dir_entry(new_pos, e);
> +            new_nb_bitmaps++;
> +        }
> +    }
> +
> +    if (!can_write(bs)) {

You should be setting ret here (gcc complains about that).

> +        goto out;
> +    }
> +
> +    ret = directory_update(bs, new_dir, new_pos - new_dir, new_nb_bitmaps);
> +    if (ret < 0) {
> +        error_setg(errp, "Can't update bitmap directory.");

And once more, please no full stops at the end of error messages.

> +        goto out;
> +    }
> +
> +    /* to be consistent, free bitmap only after successfull directory update */

*successful

> +    for_each_bitmap_dir_entry(e, dir, dir_size) {
> +        uint32_t fl = e->flags;
> +
> +        if (fl & BME_FLAG_AUTO) {
> +            free_bitmap_clusters(bs, e);
> +        }
> +    }
> +
> +out:
> +    g_free(dir);
> +    g_free(new_dir);
> +
> +    return ret;
> +}
> diff --git a/block/qcow2.c b/block/qcow2.c
> index 08c4ef9..02ec224 100644
> --- a/block/qcow2.c
> +++ b/block/qcow2.c
> @@ -213,6 +213,11 @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
>              s->bitmap_directory_size =
>                      bitmaps_ext.bitmap_directory_size;
>  
> +            ret = qcow2_read_bitmaps(bs, errp);
> +            if (ret < 0) {
> +                return ret;
> +            }
> +

I think I'd put this directly into qcow2_open(), just like
qcow2_read_snapshots(); but that's an optional suggestion.

Max

>  #ifdef DEBUG_EXT
>              printf("Qcow2: Got dirty bitmaps extension:"
>                     " offset=%" PRIu64 " nb_bitmaps=%" PRIu32 "\n",
> diff --git a/block/qcow2.h b/block/qcow2.h
> index c068b2c..482a29f 100644
> --- a/block/qcow2.h
> +++ b/block/qcow2.h
> @@ -603,6 +603,9 @@ int qcow2_snapshot_load_tmp(BlockDriverState *bs,
>  void qcow2_free_snapshots(BlockDriverState *bs);
>  int qcow2_read_snapshots(BlockDriverState *bs);
>  
> +/* qcow2-bitmap.c functions */
> +int qcow2_read_bitmaps(BlockDriverState *bs, Error **errp);
> +
>  /* qcow2-cache.c functions */
>  Qcow2Cache *qcow2_cache_create(BlockDriverState *bs, int num_tables);
>  int qcow2_cache_destroy(BlockDriverState* bs, Qcow2Cache *c);
> 



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 480 bytes --]

  reply	other threads:[~2016-10-01 16:26 UTC|newest]

Thread overview: 100+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-09-30 10:53 [Qemu-devel] [PATCH v7 00/22] qcow2: persistent dirty bitmaps Vladimir Sementsov-Ogievskiy
2016-09-30 10:53 ` [Qemu-devel] [PATCH 01/22] hbitmap: improve dirty iter Vladimir Sementsov-Ogievskiy
2016-10-01 13:52   ` Max Reitz
2016-09-30 10:53 ` [Qemu-devel] [PATCH 02/22] tests: add hbitmap iter test Vladimir Sementsov-Ogievskiy
2016-10-01 14:02   ` Max Reitz
2016-09-30 10:53 ` [Qemu-devel] [PATCH 03/22] block: fix bdrv_dirty_bitmap_granularity signature Vladimir Sementsov-Ogievskiy
2016-09-30 10:53 ` [Qemu-devel] [PATCH 04/22] block/dirty-bitmap: add deserialize_ones func Vladimir Sementsov-Ogievskiy
2016-09-30 10:53 ` [Qemu-devel] [PATCH 05/22] qcow2-bitmap: structs and consts Vladimir Sementsov-Ogievskiy
2016-10-01 14:34   ` Max Reitz
2016-10-01 14:56     ` Max Reitz
2016-10-07 13:11     ` Vladimir Sementsov-Ogievskiy
2016-10-11 11:50     ` Vladimir Sementsov-Ogievskiy
2016-10-12 18:20       ` Max Reitz
2016-09-30 10:53 ` [Qemu-devel] [PATCH 06/22] qcow2: add dirty bitmaps extension Vladimir Sementsov-Ogievskiy
2016-10-01 14:46   ` Max Reitz
2016-10-11 12:09     ` Vladimir Sementsov-Ogievskiy
2016-10-12 18:21       ` Max Reitz
2016-10-13 12:18         ` Vladimir Sementsov-Ogievskiy
2016-09-30 10:53 ` [Qemu-devel] [PATCH 07/22] qcow2-bitmap: introduce auto-loading bitmaps Vladimir Sementsov-Ogievskiy
2016-10-01 16:26   ` Max Reitz [this message]
2016-10-14 18:44     ` Vladimir Sementsov-Ogievskiy
2016-10-15 17:03       ` Max Reitz
2016-10-15 17:22         ` Vladimir Sementsov-Ogievskiy
2016-10-20 12:22     ` Vladimir Sementsov-Ogievskiy
2016-10-21 19:49       ` Max Reitz
2016-10-07 19:25   ` Max Reitz
2016-10-21 11:59     ` Vladimir Sementsov-Ogievskiy
2016-10-21 19:56       ` Max Reitz
2016-09-30 10:53 ` [Qemu-devel] [PATCH 08/22] block/dirty-bitmap: add autoload field to BdrvDirtyBitmap Vladimir Sementsov-Ogievskiy
2016-10-07 17:05   ` Max Reitz
2016-09-30 10:53 ` [Qemu-devel] [PATCH 09/22] block: introduce persistent dirty bitmaps Vladimir Sementsov-Ogievskiy
2016-10-07 17:54   ` Max Reitz
2016-10-11 13:11     ` Vladimir Sementsov-Ogievskiy
2016-10-12 18:24       ` Max Reitz
2016-10-07 19:28   ` Max Reitz
2016-10-12 11:38     ` Vladimir Sementsov-Ogievskiy
2016-10-12 12:30       ` Vladimir Sementsov-Ogievskiy
2016-10-12 18:25         ` Max Reitz
2016-09-30 10:53 ` [Qemu-devel] [PATCH 10/22] block/dirty-bitmap: add bdrv_dirty_bitmap_next() Vladimir Sementsov-Ogievskiy
2016-10-07 18:11   ` Max Reitz
2016-09-30 10:53 ` [Qemu-devel] [PATCH 11/22] qcow2-bitmap: add qcow2_store_persistent_bitmaps() Vladimir Sementsov-Ogievskiy
2016-10-07 19:24   ` Max Reitz
2016-10-13 16:48     ` Vladimir Sementsov-Ogievskiy
2016-10-15 16:40       ` Max Reitz
2016-10-17 17:19     ` Vladimir Sementsov-Ogievskiy
2016-10-21 19:44       ` Max Reitz
2016-10-21 21:04         ` Eric Blake
2016-10-17 17:57   ` Vladimir Sementsov-Ogievskiy
2016-10-17 17:58     ` [Qemu-devel] DROP THIS " Vladimir Sementsov-Ogievskiy
2016-09-30 10:53 ` [Qemu-devel] [PATCH 12/22] qcow2-bitmap: add IN_USE flag Vladimir Sementsov-Ogievskiy
2016-10-07 19:44   ` Max Reitz
2016-10-21 15:34     ` Vladimir Sementsov-Ogievskiy
2016-10-21 19:58       ` Max Reitz
2016-10-24 10:32         ` Vladimir Sementsov-Ogievskiy
2016-10-24 11:35           ` Vladimir Sementsov-Ogievskiy
2016-10-24 17:08             ` Max Reitz
2016-10-24 17:18               ` Max Reitz
2016-10-25 10:53                 ` Vladimir Sementsov-Ogievskiy
2016-10-26  9:04                   ` Vladimir Sementsov-Ogievskiy
2016-10-26  9:21                     ` Vladimir Sementsov-Ogievskiy
2016-10-26 12:13                       ` Vladimir Sementsov-Ogievskiy
2016-10-26 13:02                         ` Vladimir Sementsov-Ogievskiy
2016-10-26 15:28                     ` Max Reitz
2016-11-07 16:12                   ` Vladimir Sementsov-Ogievskiy
2016-11-07 16:18                     ` Max Reitz
2016-10-24 16:54           ` Max Reitz
2016-09-30 10:53 ` [Qemu-devel] [PATCH 13/22] qcow2-bitmap: check constraints Vladimir Sementsov-Ogievskiy
2016-10-07 19:54   ` Max Reitz
2016-09-30 10:53 ` [Qemu-devel] [PATCH 14/22] qcow2: delete bitmaps on truncate Vladimir Sementsov-Ogievskiy
2016-10-07 19:58   ` Max Reitz
2016-09-30 10:53 ` [Qemu-devel] [PATCH 15/22] qcow2-bitmap: add autoclear bit Vladimir Sementsov-Ogievskiy
2016-10-07 20:11   ` Max Reitz
2016-10-24 14:25     ` Vladimir Sementsov-Ogievskiy
2016-10-24 17:21       ` Max Reitz
2016-09-30 10:53 ` [Qemu-devel] [PATCH 16/22] qmp: add persistent flag to block-dirty-bitmap-add Vladimir Sementsov-Ogievskiy
2016-10-07 19:52   ` Eric Blake
2016-10-24 14:44     ` Vladimir Sementsov-Ogievskiy
2016-10-10 16:08   ` Max Reitz
2016-10-24 15:12     ` Vladimir Sementsov-Ogievskiy
2016-10-24 17:30       ` Max Reitz
2016-10-25 11:05         ` Vladimir Sementsov-Ogievskiy
2016-09-30 10:53 ` [Qemu-devel] [PATCH 17/22] qmp: add autoload parameter " Vladimir Sementsov-Ogievskiy
2016-10-07 19:53   ` Eric Blake
2016-10-10 16:25   ` Max Reitz
2016-10-24 15:55     ` Vladimir Sementsov-Ogievskiy
2016-09-30 10:53 ` [Qemu-devel] [PATCH 18/22] qapi: add md5 checksum of last dirty bitmap level to query-block Vladimir Sementsov-Ogievskiy
2016-10-10 16:44   ` Max Reitz
2016-10-10 17:03     ` Max Reitz
2016-10-10 19:22       ` Eric Blake
2016-09-30 10:53 ` [Qemu-devel] [PATCH 19/22] iotests: test qcow2 persistent dirty bitmap Vladimir Sementsov-Ogievskiy
2016-10-10 17:04   ` Max Reitz
2016-09-30 10:53 ` [Qemu-devel] [PATCH 20/22] qcow2-dirty-bitmap: refcounts Vladimir Sementsov-Ogievskiy
2016-10-10 17:59   ` Max Reitz
2016-09-30 10:53 ` [Qemu-devel] [PATCH 21/22] specs/qcow2: fix bitmap granularity qemu-specific note Vladimir Sementsov-Ogievskiy
2016-10-07 20:18   ` Eric Blake
2016-11-09 16:43     ` Vladimir Sementsov-Ogievskiy
2016-09-30 10:53 ` [Qemu-devel] [PATCH 22/22] specs/qcow2: do not use wording 'bitmap header' Vladimir Sementsov-Ogievskiy
2016-10-07 20:20   ` Eric Blake
2016-10-01 13:37 ` [Qemu-devel] [PATCH v7 00/22] qcow2: persistent dirty bitmaps Max Reitz
2016-10-13 18:11   ` John Snow

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=93be46ce-5b73-c7d3-ada0-d59461227dbf@redhat.com \
    --to=mreitz@redhat.com \
    --cc=armbru@redhat.com \
    --cc=den@openvz.org \
    --cc=eblake@redhat.com \
    --cc=famz@redhat.com \
    --cc=jsnow@redhat.com \
    --cc=kwolf@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=qemu-block@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    --cc=stefanha@redhat.com \
    --cc=vsementsov@virtuozzo.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.