Commit 9cc7d0cf authored by Peter Maydell's avatar Peter Maydell
Browse files

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



# gpg: Signature made Tue 13 Mar 2018 21:11:43 GMT
# gpg:                using RSA key 7DEF8106AAFC390E
# gpg: Good signature from "John Snow (John Huston) <jsnow@redhat.com>"
# 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: add dirty bitmap postcopy test
  iotests: add dirty bitmap migration test
  migration: add postcopy migration of dirty bitmaps
  migration: allow qmp command migrate-start-postcopy for any postcopy
  migration: add is_active_iterate handler
  migration/qemu-file: add qemu_put_counted_string()
  migration: include migrate_dirty_bitmaps in migrate_postcopy
  qapi: add dirty-bitmaps migration capability
  migration: introduce postcopy-only pending
  dirty-bitmap: add locked state
  block/dirty-bitmap: add _locked version of bdrv_reclaim_dirty_bitmap
  block/dirty-bitmap: fix locking in bdrv_reclaim_dirty_bitmap
  block/dirty-bitmap: add bdrv_dirty_bitmap_enable_successor()

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 475fe457 ac8bd439
Loading
Loading
Loading
Loading
+88 −35
Original line number Diff line number Diff line
@@ -40,6 +40,8 @@ struct BdrvDirtyBitmap {
    QemuMutex *mutex;
    HBitmap *bitmap;            /* Dirty bitmap implementation */
    HBitmap *meta;              /* Meta dirty bitmap */
    bool qmp_locked;            /* Bitmap is locked, it can't be modified
                                   through QMP */
    BdrvDirtyBitmap *successor; /* Anonymous child; implies frozen status */
    char *name;                 /* Optional non-empty unique ID */
    int64_t size;               /* Size of the bitmap, in bytes */
@@ -183,6 +185,18 @@ bool bdrv_dirty_bitmap_frozen(BdrvDirtyBitmap *bitmap)
    return bitmap->successor;
}

void bdrv_dirty_bitmap_set_qmp_locked(BdrvDirtyBitmap *bitmap, bool qmp_locked)
{
    qemu_mutex_lock(bitmap->mutex);
    bitmap->qmp_locked = qmp_locked;
    qemu_mutex_unlock(bitmap->mutex);
}

bool bdrv_dirty_bitmap_qmp_locked(BdrvDirtyBitmap *bitmap)
{
    return bitmap->qmp_locked;
}

/* Called with BQL taken.  */
bool bdrv_dirty_bitmap_enabled(BdrvDirtyBitmap *bitmap)
{
@@ -194,6 +208,8 @@ DirtyBitmapStatus bdrv_dirty_bitmap_status(BdrvDirtyBitmap *bitmap)
{
    if (bdrv_dirty_bitmap_frozen(bitmap)) {
        return DIRTY_BITMAP_STATUS_FROZEN;
    } else if (bdrv_dirty_bitmap_qmp_locked(bitmap)) {
        return DIRTY_BITMAP_STATUS_LOCKED;
    } else if (!bdrv_dirty_bitmap_enabled(bitmap)) {
        return DIRTY_BITMAP_STATUS_DISABLED;
    } else {
@@ -234,6 +250,59 @@ int bdrv_dirty_bitmap_create_successor(BlockDriverState *bs,
    return 0;
}

/* Called with BQL taken. */
void bdrv_dirty_bitmap_enable_successor(BdrvDirtyBitmap *bitmap)
{
    qemu_mutex_lock(bitmap->mutex);
    bdrv_enable_dirty_bitmap(bitmap->successor);
    qemu_mutex_unlock(bitmap->mutex);
}

/* Called within bdrv_dirty_bitmap_lock..unlock */
static void bdrv_do_release_matching_dirty_bitmap_locked(
    BlockDriverState *bs, BdrvDirtyBitmap *bitmap,
    bool (*cond)(BdrvDirtyBitmap *bitmap))
{
    BdrvDirtyBitmap *bm, *next;

    QLIST_FOREACH_SAFE(bm, &bs->dirty_bitmaps, list, next) {
        if ((!bitmap || bm == bitmap) && (!cond || cond(bm))) {
            assert(!bm->active_iterators);
            assert(!bdrv_dirty_bitmap_frozen(bm));
            assert(!bm->meta);
            QLIST_REMOVE(bm, list);
            hbitmap_free(bm->bitmap);
            g_free(bm->name);
            g_free(bm);

            if (bitmap) {
                return;
            }
        }
    }

    if (bitmap) {
        abort();
    }
}

/* Called with BQL taken.  */
static void bdrv_do_release_matching_dirty_bitmap(
    BlockDriverState *bs, BdrvDirtyBitmap *bitmap,
    bool (*cond)(BdrvDirtyBitmap *bitmap))
{
    bdrv_dirty_bitmaps_lock(bs);
    bdrv_do_release_matching_dirty_bitmap_locked(bs, bitmap, cond);
    bdrv_dirty_bitmaps_unlock(bs);
}

/* Called within bdrv_dirty_bitmap_lock..unlock */
static void bdrv_release_dirty_bitmap_locked(BlockDriverState *bs,
                                             BdrvDirtyBitmap *bitmap)
{
    bdrv_do_release_matching_dirty_bitmap_locked(bs, bitmap, NULL);
}

/**
 * For a bitmap with a successor, yield our name to the successor,
 * delete the old bitmap, and return a handle to the new bitmap.
@@ -267,9 +336,9 @@ BdrvDirtyBitmap *bdrv_dirty_bitmap_abdicate(BlockDriverState *bs,
 * In cases of failure where we can no longer safely delete the parent,
 * we may wish to re-join the parent and child/successor.
 * The merged parent will be un-frozen, but not explicitly re-enabled.
 * Called with BQL taken.
 * Called within bdrv_dirty_bitmap_lock..unlock and with BQL taken.
 */
BdrvDirtyBitmap *bdrv_reclaim_dirty_bitmap(BlockDriverState *bs,
BdrvDirtyBitmap *bdrv_reclaim_dirty_bitmap_locked(BlockDriverState *bs,
                                                  BdrvDirtyBitmap *parent,
                                                  Error **errp)
{
@@ -284,12 +353,26 @@ BdrvDirtyBitmap *bdrv_reclaim_dirty_bitmap(BlockDriverState *bs,
        error_setg(errp, "Merging of parent and successor bitmap failed");
        return NULL;
    }
    bdrv_release_dirty_bitmap(bs, successor);
    bdrv_release_dirty_bitmap_locked(bs, successor);
    parent->successor = NULL;

    return parent;
}

/* Called with BQL taken. */
BdrvDirtyBitmap *bdrv_reclaim_dirty_bitmap(BlockDriverState *bs,
                                           BdrvDirtyBitmap *parent,
                                           Error **errp)
{
    BdrvDirtyBitmap *ret;

    qemu_mutex_lock(parent->mutex);
    ret = bdrv_reclaim_dirty_bitmap_locked(bs, parent, errp);
    qemu_mutex_unlock(parent->mutex);

    return ret;
}

/**
 * Truncates _all_ bitmaps attached to a BDS.
 * Called with BQL taken.
@@ -313,36 +396,6 @@ static bool bdrv_dirty_bitmap_has_name(BdrvDirtyBitmap *bitmap)
    return !!bdrv_dirty_bitmap_name(bitmap);
}

/* Called with BQL taken.  */
static void bdrv_do_release_matching_dirty_bitmap(
    BlockDriverState *bs, BdrvDirtyBitmap *bitmap,
    bool (*cond)(BdrvDirtyBitmap *bitmap))
{
    BdrvDirtyBitmap *bm, *next;
    bdrv_dirty_bitmaps_lock(bs);
    QLIST_FOREACH_SAFE(bm, &bs->dirty_bitmaps, list, next) {
        if ((!bitmap || bm == bitmap) && (!cond || cond(bm))) {
            assert(!bm->active_iterators);
            assert(!bdrv_dirty_bitmap_frozen(bm));
            assert(!bm->meta);
            QLIST_REMOVE(bm, list);
            hbitmap_free(bm->bitmap);
            g_free(bm->name);
            g_free(bm);

            if (bitmap) {
                goto out;
            }
        }
    }
    if (bitmap) {
        abort();
    }

out:
    bdrv_dirty_bitmaps_unlock(bs);
}

/* Called with BQL taken.  */
void bdrv_release_dirty_bitmap(BlockDriverState *bs, BdrvDirtyBitmap *bitmap)
{
+19 −0
Original line number Diff line number Diff line
@@ -2118,6 +2118,9 @@ static void block_dirty_bitmap_clear_prepare(BlkActionState *common,
    if (bdrv_dirty_bitmap_frozen(state->bitmap)) {
        error_setg(errp, "Cannot modify a frozen bitmap");
        return;
    } else if (bdrv_dirty_bitmap_qmp_locked(state->bitmap)) {
        error_setg(errp, "Cannot modify a locked bitmap");
        return;
    } else if (!bdrv_dirty_bitmap_enabled(state->bitmap)) {
        error_setg(errp, "Cannot clear a disabled bitmap");
        return;
@@ -2862,6 +2865,11 @@ void qmp_block_dirty_bitmap_remove(const char *node, const char *name,
                   "Bitmap '%s' is currently frozen and cannot be removed",
                   name);
        return;
    } else if (bdrv_dirty_bitmap_qmp_locked(bitmap)) {
        error_setg(errp,
                   "Bitmap '%s' is currently locked and cannot be removed",
                   name);
        return;
    }

    if (bdrv_dirty_bitmap_get_persistance(bitmap)) {
@@ -2896,6 +2904,11 @@ void qmp_block_dirty_bitmap_clear(const char *node, const char *name,
                   "Bitmap '%s' is currently frozen and cannot be modified",
                   name);
        return;
    } else if (bdrv_dirty_bitmap_qmp_locked(bitmap)) {
        error_setg(errp,
                   "Bitmap '%s' is currently locked and cannot be modified",
                   name);
        return;
    } else if (!bdrv_dirty_bitmap_enabled(bitmap)) {
        error_setg(errp,
                   "Bitmap '%s' is currently disabled and cannot be cleared",
@@ -3370,6 +3383,12 @@ static BlockJob *do_drive_backup(DriveBackup *backup, BlockJobTxn *txn,
            bdrv_unref(target_bs);
            goto out;
        }
        if (bdrv_dirty_bitmap_qmp_locked(bmap)) {
            error_setg(errp,
                       "Bitmap '%s' is currently locked and cannot be used for "
                       "backup", backup->bitmap);
            goto out;
        }
    }

    job = backup_job_create(backup->job_id, bs, target_bs, backup->speed,
+4 −3
Original line number Diff line number Diff line
@@ -183,15 +183,16 @@ static int cmma_save_setup(QEMUFile *f, void *opaque)
}

static void cmma_save_pending(QEMUFile *f, void *opaque, uint64_t max_size,
                             uint64_t *non_postcopiable_pending,
                             uint64_t *postcopiable_pending)
                              uint64_t *res_precopy_only,
                              uint64_t *res_compatible,
                              uint64_t *res_postcopy_only)
{
    S390StAttribState *sas = S390_STATTRIB(opaque);
    S390StAttribClass *sac = S390_STATTRIB_GET_CLASS(sas);
    long long res = sac->get_dirtycount(sas);

    if (res >= 0) {
        *non_postcopiable_pending += res;
        *res_precopy_only += res;
    }
}

+7 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ BdrvDirtyBitmap *bdrv_dirty_bitmap_abdicate(BlockDriverState *bs,
BdrvDirtyBitmap *bdrv_reclaim_dirty_bitmap(BlockDriverState *bs,
                                           BdrvDirtyBitmap *bitmap,
                                           Error **errp);
void bdrv_dirty_bitmap_enable_successor(BdrvDirtyBitmap *bitmap);
BdrvDirtyBitmap *bdrv_find_dirty_bitmap(BlockDriverState *bs,
                                        const char *name);
void bdrv_dirty_bitmap_make_anon(BdrvDirtyBitmap *bitmap);
@@ -68,6 +69,8 @@ void bdrv_dirty_bitmap_deserialize_finish(BdrvDirtyBitmap *bitmap);
void bdrv_dirty_bitmap_set_readonly(BdrvDirtyBitmap *bitmap, bool value);
void bdrv_dirty_bitmap_set_persistance(BdrvDirtyBitmap *bitmap,
                                       bool persistent);
void bdrv_dirty_bitmap_set_qmp_locked(BdrvDirtyBitmap *bitmap, bool qmp_locked);


/* Functions that require manual locking.  */
void bdrv_dirty_bitmap_lock(BdrvDirtyBitmap *bitmap);
@@ -87,10 +90,14 @@ bool bdrv_dirty_bitmap_readonly(const BdrvDirtyBitmap *bitmap);
bool bdrv_has_readonly_bitmaps(BlockDriverState *bs);
bool bdrv_dirty_bitmap_get_autoload(const BdrvDirtyBitmap *bitmap);
bool bdrv_dirty_bitmap_get_persistance(BdrvDirtyBitmap *bitmap);
bool bdrv_dirty_bitmap_qmp_locked(BdrvDirtyBitmap *bitmap);
bool bdrv_has_changed_persistent_bitmaps(BlockDriverState *bs);
BdrvDirtyBitmap *bdrv_dirty_bitmap_next(BlockDriverState *bs,
                                        BdrvDirtyBitmap *bitmap);
char *bdrv_dirty_bitmap_sha256(const BdrvDirtyBitmap *bitmap, Error **errp);
int64_t bdrv_dirty_bitmap_next_zero(BdrvDirtyBitmap *bitmap, uint64_t start);
BdrvDirtyBitmap *bdrv_reclaim_dirty_bitmap_locked(BlockDriverState *bs,
                                                  BdrvDirtyBitmap *bitmap,
                                                  Error **errp);

#endif
+3 −0
Original line number Diff line number Diff line
@@ -56,4 +56,7 @@ bool migration_has_failed(MigrationState *);
bool migration_in_postcopy_after_devices(MigrationState *);
void migration_global_dump(Monitor *mon);

/* migration/block-dirty-bitmap.c */
void dirty_bitmap_mig_init(void);

#endif
Loading