Commit fa000f2f authored by Vladimir Sementsov-Ogievskiy's avatar Vladimir Sementsov-Ogievskiy Committed by John Snow
Browse files

dirty-bitmap: make it possible to restore bitmap after merge



Add backup parameter to bdrv_merge_dirty_bitmap() to be used then with
bdrv_restore_dirty_bitmap() if it needed to restore the bitmap after
merge operation.

This is needed to implement bitmap merge transaction action in further
commit.

Signed-off-by: default avatarVladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Reviewed-by: default avatarJohn Snow <jsnow@redhat.com>
parent 56bd6624
Loading
Loading
Loading
Loading
+14 −3
Original line number Diff line number Diff line
@@ -314,7 +314,7 @@ BdrvDirtyBitmap *bdrv_reclaim_dirty_bitmap_locked(BlockDriverState *bs,
        return NULL;
    }

    if (!hbitmap_merge(parent->bitmap, successor->bitmap)) {
    if (!hbitmap_merge(parent->bitmap, successor->bitmap, parent->bitmap)) {
        error_setg(errp, "Merging of parent and successor bitmap failed");
        return NULL;
    }
@@ -791,8 +791,10 @@ int64_t bdrv_dirty_bitmap_next_zero(BdrvDirtyBitmap *bitmap, uint64_t offset)
}

void bdrv_merge_dirty_bitmap(BdrvDirtyBitmap *dest, const BdrvDirtyBitmap *src,
                             Error **errp)
                             HBitmap **backup, Error **errp)
{
    bool ret;

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

@@ -810,11 +812,20 @@ void bdrv_merge_dirty_bitmap(BdrvDirtyBitmap *dest, const BdrvDirtyBitmap *src,
        goto out;
    }

    if (!hbitmap_merge(dest->bitmap, src->bitmap)) {
    if (!hbitmap_can_merge(dest->bitmap, src->bitmap)) {
        error_setg(errp, "Bitmaps are incompatible and can't be merged");
        goto out;
    }

    if (backup) {
        *backup = dest->bitmap;
        dest->bitmap = hbitmap_alloc(dest->size, hbitmap_granularity(*backup));
        ret = hbitmap_merge(*backup, src->bitmap, dest->bitmap);
    } else {
        ret = hbitmap_merge(dest->bitmap, src->bitmap, dest->bitmap);
    }
    assert(ret);

out:
    qemu_mutex_unlock(dest->mutex);
}
+1 −1
Original line number Diff line number Diff line
@@ -2968,7 +2968,7 @@ void qmp_x_block_dirty_bitmap_merge(const char *node, const char *dst_name,
        return;
    }

    bdrv_merge_dirty_bitmap(dst, src, errp);
    bdrv_merge_dirty_bitmap(dst, src, NULL, errp);
}

BlockDirtyBitmapSha256 *qmp_x_debug_block_dirty_bitmap_sha256(const char *node,
+1 −1
Original line number Diff line number Diff line
@@ -71,7 +71,7 @@ void bdrv_dirty_bitmap_set_persistance(BdrvDirtyBitmap *bitmap,
                                       bool persistent);
void bdrv_dirty_bitmap_set_qmp_locked(BdrvDirtyBitmap *bitmap, bool qmp_locked);
void bdrv_merge_dirty_bitmap(BdrvDirtyBitmap *dest, const BdrvDirtyBitmap *src,
                             Error **errp);
                             HBitmap **backup, Error **errp);

/* Functions that require manual locking.  */
void bdrv_dirty_bitmap_lock(BdrvDirtyBitmap *bitmap);
+16 −9
Original line number Diff line number Diff line
@@ -73,16 +73,23 @@ void hbitmap_truncate(HBitmap *hb, uint64_t size);

/**
 * hbitmap_merge:
 * @a: The bitmap to store the result in.
 * @b: The bitmap to merge into @a.
 * @return true if the merge was successful,
 *
 * Store result of merging @a and @b into @result.
 * @result is allowed to be equal to @a or @b.
 *
 * Return true if the merge was successful,
 *        false if it was not attempted.
 */
bool hbitmap_merge(const HBitmap *a, const HBitmap *b, HBitmap *result);

/**
 * hbitmap_can_merge:
 *
 * hbitmap_can_merge(a, b) && hbitmap_can_merge(a, result) is sufficient and
 * necessary for hbitmap_merge will not fail.
 *
 * Merge two bitmaps together.
 * A := A (BITOR) B.
 * B is left unmodified.
 */
bool hbitmap_merge(HBitmap *a, const HBitmap *b);
bool hbitmap_can_merge(const HBitmap *a, const HBitmap *b);

/**
 * hbitmap_empty:
+8 −3
Original line number Diff line number Diff line
@@ -723,6 +723,10 @@ void hbitmap_truncate(HBitmap *hb, uint64_t size)
    }
}

bool hbitmap_can_merge(const HBitmap *a, const HBitmap *b)
{
    return (a->size == b->size) && (a->granularity == b->granularity);
}

/**
 * Given HBitmaps A and B, let A := A (BITOR) B.
@@ -731,14 +735,15 @@ void hbitmap_truncate(HBitmap *hb, uint64_t size)
 * @return true if the merge was successful,
 *         false if it was not attempted.
 */
bool hbitmap_merge(HBitmap *a, const HBitmap *b)
bool hbitmap_merge(const HBitmap *a, const HBitmap *b, HBitmap *result)
{
    int i;
    uint64_t j;

    if ((a->size != b->size) || (a->granularity != b->granularity)) {
    if (!hbitmap_can_merge(a, b) || !hbitmap_can_merge(a, result)) {
        return false;
    }
    assert(hbitmap_can_merge(b, result));

    if (hbitmap_count(b) == 0) {
        return true;
@@ -750,7 +755,7 @@ bool hbitmap_merge(HBitmap *a, const HBitmap *b)
     */
    for (i = HBITMAP_LEVELS - 1; i >= 0; i--) {
        for (j = 0; j < a->sizes[i]; j++) {
            a->levels[i][j] |= b->levels[i][j];
            result->levels[i][j] = a->levels[i][j] | b->levels[i][j];
        }
    }