Commit 62f6849e authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/jnsnow/tags/bitmaps-pull-request' into staging



Pull request

# gpg: Signature made Wed 29 May 2019 00:58:33 BST
# gpg:                using RSA key F9B7ABDBBCACDF95BE76CBD07DEF8106AAFC390E
# gpg: Good signature from "John Snow (John Huston) <jsnow@redhat.com>" [full]
# Primary key fingerprint: FAEB 9711 A12C F475 812F  18F2 88A9 064D 1835 61EB
#      Subkey fingerprint: F9B7 ABDB BCAC DF95 BE76  CBD0 7DEF 8106 AAFC 390E

* remotes/jnsnow/tags/bitmaps-pull-request:
  iotests: test external snapshot with bitmap copying
  qapi: support external bitmaps in block-dirty-bitmap-merge
  migration/dirty-bitmaps: change bitmap enumeration method

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents e5714b5b 403bb818
Loading
Loading
Loading
Loading
+6 −3
Original line number Diff line number Diff line
@@ -816,10 +816,10 @@ void bdrv_merge_dirty_bitmap(BdrvDirtyBitmap *dest, const BdrvDirtyBitmap *src,
{
    bool ret;

    /* only bitmaps from one bds are supported */
    assert(dest->mutex == src->mutex);

    qemu_mutex_lock(dest->mutex);
    if (src->mutex != dest->mutex) {
        qemu_mutex_lock(src->mutex);
    }

    if (bdrv_dirty_bitmap_check(dest, BDRV_BITMAP_DEFAULT, errp)) {
        goto out;
@@ -845,4 +845,7 @@ void bdrv_merge_dirty_bitmap(BdrvDirtyBitmap *dest, const BdrvDirtyBitmap *src,

out:
    qemu_mutex_unlock(dest->mutex);
    if (src->mutex != dest->mutex) {
        qemu_mutex_unlock(src->mutex);
    }
}
+33 −17
Original line number Diff line number Diff line
@@ -2112,11 +2112,10 @@ static void block_dirty_bitmap_disable_abort(BlkActionState *common)
    }
}

static BdrvDirtyBitmap *do_block_dirty_bitmap_merge(const char *node,
                                                    const char *target,
                                                    strList *bitmaps,
                                                    HBitmap **backup,
                                                    Error **errp);
static BdrvDirtyBitmap *do_block_dirty_bitmap_merge(
        const char *node, const char *target,
        BlockDirtyBitmapMergeSourceList *bitmaps,
        HBitmap **backup, Error **errp);

static void block_dirty_bitmap_merge_prepare(BlkActionState *common,
                                             Error **errp)
@@ -2965,15 +2964,14 @@ void qmp_block_dirty_bitmap_disable(const char *node, const char *name,
    bdrv_disable_dirty_bitmap(bitmap);
}

static BdrvDirtyBitmap *do_block_dirty_bitmap_merge(const char *node,
                                                    const char *target,
                                                    strList *bitmaps,
                                                    HBitmap **backup,
                                                    Error **errp)
static BdrvDirtyBitmap *do_block_dirty_bitmap_merge(
        const char *node, const char *target,
        BlockDirtyBitmapMergeSourceList *bitmaps,
        HBitmap **backup, Error **errp)
{
    BlockDriverState *bs;
    BdrvDirtyBitmap *dst, *src, *anon;
    strList *lst;
    BlockDirtyBitmapMergeSourceList *lst;
    Error *local_err = NULL;

    dst = block_dirty_bitmap_lookup(node, target, &bs, errp);
@@ -2988,12 +2986,29 @@ static BdrvDirtyBitmap *do_block_dirty_bitmap_merge(const char *node,
    }

    for (lst = bitmaps; lst; lst = lst->next) {
        src = bdrv_find_dirty_bitmap(bs, lst->value);
        switch (lst->value->type) {
            const char *name, *node;
        case QTYPE_QSTRING:
            name = lst->value->u.local;
            src = bdrv_find_dirty_bitmap(bs, name);
            if (!src) {
            error_setg(errp, "Dirty bitmap '%s' not found", lst->value);
                error_setg(errp, "Dirty bitmap '%s' not found", name);
                dst = NULL;
                goto out;
            }
            break;
        case QTYPE_QDICT:
            node = lst->value->u.external.node;
            name = lst->value->u.external.name;
            src = block_dirty_bitmap_lookup(node, name, NULL, errp);
            if (!src) {
                dst = NULL;
                goto out;
            }
            break;
        default:
            abort();
        }

        bdrv_merge_dirty_bitmap(anon, src, NULL, &local_err);
        if (local_err) {
@@ -3012,7 +3027,8 @@ static BdrvDirtyBitmap *do_block_dirty_bitmap_merge(const char *node,
}

void qmp_block_dirty_bitmap_merge(const char *node, const char *target,
                                  strList *bitmaps, Error **errp)
                                  BlockDirtyBitmapMergeSourceList *bitmaps,
                                  Error **errp)
{
    do_block_dirty_bitmap_merge(node, target, bitmaps, NULL, errp);
}
+4 −10
Original line number Diff line number Diff line
@@ -273,7 +273,6 @@ static int init_dirty_bitmap_migration(void)
    BlockDriverState *bs;
    BdrvDirtyBitmap *bitmap;
    DirtyBitmapMigBitmapState *dbms;
    BdrvNextIterator it;
    Error *local_err = NULL;

    dirty_bitmap_mig_state.bulk_completed = false;
@@ -281,13 +280,8 @@ static int init_dirty_bitmap_migration(void)
    dirty_bitmap_mig_state.prev_bitmap = NULL;
    dirty_bitmap_mig_state.no_bitmaps = false;

    for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) {
        const char *drive_name = bdrv_get_device_or_node_name(bs);

        /* skip automatically inserted nodes */
        while (bs && bs->drv && bs->implicit) {
            bs = backing_bs(bs);
        }
    for (bs = bdrv_next_all_states(NULL); bs; bs = bdrv_next_all_states(bs)) {
        const char *name = bdrv_get_device_or_node_name(bs);

        for (bitmap = bdrv_dirty_bitmap_next(bs, NULL); bitmap;
             bitmap = bdrv_dirty_bitmap_next(bs, bitmap))
@@ -296,7 +290,7 @@ static int init_dirty_bitmap_migration(void)
                continue;
            }

            if (drive_name == NULL) {
            if (!name || strcmp(name, "") == 0) {
                error_report("Found bitmap '%s' in unnamed node %p. It can't "
                             "be migrated", bdrv_dirty_bitmap_name(bitmap), bs);
                goto fail;
@@ -313,7 +307,7 @@ static int init_dirty_bitmap_migration(void)

            dbms = g_new0(DirtyBitmapMigBitmapState, 1);
            dbms->bs = bs;
            dbms->node_name = drive_name;
            dbms->node_name = name;
            dbms->bitmap = bitmap;
            dbms->total_sectors = bdrv_nb_sectors(bs);
            dbms->sectors_per_chunk = CHUNK_SIZE * 8 *
+19 −3
Original line number Diff line number Diff line
@@ -2003,19 +2003,35 @@
  'data': { 'node': 'str', 'name': 'str', '*granularity': 'uint32',
            '*persistent': 'bool', '*autoload': 'bool', '*disabled': 'bool' } }

##
# @BlockDirtyBitmapMergeSource:
#
# @local: name of the bitmap, attached to the same node as target bitmap.
#
# @external: bitmap with specified node
#
# Since: 4.1
##
{ 'alternate': 'BlockDirtyBitmapMergeSource',
  'data': { 'local': 'str',
            'external': 'BlockDirtyBitmap' } }

##
# @BlockDirtyBitmapMerge:
#
# @node: name of device/node which the bitmap is tracking
# @node: name of device/node which the @target bitmap is tracking
#
# @target: name of the destination dirty bitmap
#
# @bitmaps: name(s) of the source dirty bitmap(s)
# @bitmaps: name(s) of the source dirty bitmap(s) at @node and/or fully
#           specifed BlockDirtyBitmap elements. The latter are supported
#           since 4.1.
#
# Since: 4.0
##
{ 'struct': 'BlockDirtyBitmapMerge',
  'data': { 'node': 'str', 'target': 'str', 'bitmaps': ['str'] } }
  'data': { 'node': 'str', 'target': 'str',
            'bitmaps': ['BlockDirtyBitmapMergeSource'] } }

##
# @block-dirty-bitmap-add:

tests/qemu-iotests/254

0 → 100755
+52 −0
Original line number Diff line number Diff line
#!/usr/bin/env python
#
# Test external snapshot with bitmap copying.
#
# Copyright (c) 2019 Virtuozzo International GmbH. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#

import iotests
from iotests import qemu_img_create, file_path, log

disk, top = file_path('disk', 'top')
size = 1024 * 1024

qemu_img_create('-f', iotests.imgfmt, disk, str(size))

vm = iotests.VM().add_drive(disk, opts='node-name=base')
vm.launch()

vm.qmp_log('block-dirty-bitmap-add', node='drive0', name='bitmap0')

vm.hmp_qemu_io('drive0', 'write 0 512K')

vm.qmp_log('transaction', indent=2, actions=[
    {'type': 'blockdev-snapshot-sync',
     'data': {'device': 'drive0', 'snapshot-file': top,
              'snapshot-node-name': 'snap'}},
    {'type': 'block-dirty-bitmap-add',
     'data': {'node': 'snap', 'name': 'bitmap0'}},
    {'type': 'block-dirty-bitmap-merge',
     'data': {'node': 'snap', 'target': 'bitmap0',
              'bitmaps': [{'node': 'base', 'name': 'bitmap0'}]}}
], filters=[iotests.filter_qmp_testfiles])

result = vm.qmp('query-block')['return'][0]
log("query-block: device = {}, node-name = {}, dirty-bitmaps:".format(
    result['device'], result['inserted']['node-name']))
log(result['dirty-bitmaps'], indent=2)

vm.shutdown()
Loading