Commit 681d6136 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 16 Jan 2019 01:00:25 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:
  Revert "hbitmap: Add @advance param to hbitmap_iter_next()"
  Revert "test-hbitmap: Add non-advancing iter_next tests"
  Revert "block/dirty-bitmap: Add bdrv_dirty_iter_next_area"
  block/mirror: fix and improve do_sync_target_write
  tests: add tests for hbitmap_next_dirty_area
  dirty-bitmap: add bdrv_dirty_bitmap_next_dirty_area
  tests: add tests for hbitmap_next_zero with specified end parameter
  dirty-bitmap: improve bdrv_dirty_bitmap_next_zero

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 6f2f3417 19c021e1
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -385,7 +385,7 @@ static int coroutine_fn backup_run_incremental(BackupBlockJob *job)
    HBitmapIter hbi;

    hbitmap_iter_init(&hbi, job->copy_bitmap, 0);
    while ((cluster = hbitmap_iter_next(&hbi, true)) != -1) {
    while ((cluster = hbitmap_iter_next(&hbi)) != -1) {
        do {
            if (yield_and_check(job)) {
                return 0;
@@ -422,7 +422,8 @@ static void backup_incremental_init_copy_bitmap(BackupBlockJob *job)
            break;
        }

        offset = bdrv_dirty_bitmap_next_zero(job->sync_bitmap, offset);
        offset = bdrv_dirty_bitmap_next_zero(job->sync_bitmap, offset,
                                             UINT64_MAX);
        if (offset == -1) {
            hbitmap_set(job->copy_bitmap, cluster, end - cluster);
            break;
+10 −58
Original line number Diff line number Diff line
@@ -515,62 +515,7 @@ void bdrv_dirty_iter_free(BdrvDirtyBitmapIter *iter)

int64_t bdrv_dirty_iter_next(BdrvDirtyBitmapIter *iter)
{
    return hbitmap_iter_next(&iter->hbi, true);
}

/**
 * Return the next consecutively dirty area in the dirty bitmap
 * belonging to the given iterator @iter.
 *
 * @max_offset: Maximum value that may be returned for
 *              *offset + *bytes
 * @offset:     Will contain the start offset of the next dirty area
 * @bytes:      Will contain the length of the next dirty area
 *
 * Returns: True if a dirty area could be found before max_offset
 *          (which means that *offset and *bytes then contain valid
 *          values), false otherwise.
 *
 * Note that @iter is never advanced if false is returned.  If an area
 * is found (which means that true is returned), it will be advanced
 * past that area.
 */
bool bdrv_dirty_iter_next_area(BdrvDirtyBitmapIter *iter, uint64_t max_offset,
                               uint64_t *offset, int *bytes)
{
    uint32_t granularity = bdrv_dirty_bitmap_granularity(iter->bitmap);
    uint64_t gran_max_offset;
    int64_t ret;
    int size;

    if (max_offset == iter->bitmap->size) {
        /* If max_offset points to the image end, round it up by the
         * bitmap granularity */
        gran_max_offset = ROUND_UP(max_offset, granularity);
    } else {
        gran_max_offset = max_offset;
    }

    ret = hbitmap_iter_next(&iter->hbi, false);
    if (ret < 0 || ret + granularity > gran_max_offset) {
        return false;
    }

    *offset = ret;
    size = 0;

    assert(granularity <= INT_MAX);

    do {
        /* Advance iterator */
        ret = hbitmap_iter_next(&iter->hbi, true);
        size += granularity;
    } while (ret + granularity <= gran_max_offset &&
             hbitmap_iter_next(&iter->hbi, false) == ret + granularity &&
             size <= INT_MAX - granularity);

    *bytes = MIN(size, max_offset - *offset);
    return true;
    return hbitmap_iter_next(&iter->hbi);
}

/* Called within bdrv_dirty_bitmap_lock..unlock */
@@ -781,9 +726,16 @@ char *bdrv_dirty_bitmap_sha256(const BdrvDirtyBitmap *bitmap, Error **errp)
    return hbitmap_sha256(bitmap->bitmap, errp);
}

int64_t bdrv_dirty_bitmap_next_zero(BdrvDirtyBitmap *bitmap, uint64_t offset)
int64_t bdrv_dirty_bitmap_next_zero(BdrvDirtyBitmap *bitmap, uint64_t offset,
                                    uint64_t bytes)
{
    return hbitmap_next_zero(bitmap->bitmap, offset, bytes);
}

bool bdrv_dirty_bitmap_next_dirty_area(BdrvDirtyBitmap *bitmap,
                                       uint64_t *offset, uint64_t *bytes)
{
    return hbitmap_next_zero(bitmap->bitmap, offset);
    return hbitmap_next_dirty_area(bitmap->bitmap, offset, bytes);
}

void bdrv_merge_dirty_bitmap(BdrvDirtyBitmap *dest, const BdrvDirtyBitmap *src,
+8 −9
Original line number Diff line number Diff line
@@ -1185,25 +1185,23 @@ do_sync_target_write(MirrorBlockJob *job, MirrorMethod method,
                     uint64_t offset, uint64_t bytes,
                     QEMUIOVector *qiov, int flags)
{
    BdrvDirtyBitmapIter *iter;
    QEMUIOVector target_qiov;
    uint64_t dirty_offset;
    int dirty_bytes;
    uint64_t dirty_offset = offset;
    uint64_t dirty_bytes;

    if (qiov) {
        qemu_iovec_init(&target_qiov, qiov->niov);
    }

    iter = bdrv_dirty_iter_new(job->dirty_bitmap);
    bdrv_set_dirty_iter(iter, offset);

    while (true) {
        bool valid_area;
        int ret;

        bdrv_dirty_bitmap_lock(job->dirty_bitmap);
        valid_area = bdrv_dirty_iter_next_area(iter, offset + bytes,
                                               &dirty_offset, &dirty_bytes);
        dirty_bytes = MIN(offset + bytes - dirty_offset, INT_MAX);
        valid_area = bdrv_dirty_bitmap_next_dirty_area(job->dirty_bitmap,
                                                       &dirty_offset,
                                                       &dirty_bytes);
        if (!valid_area) {
            bdrv_dirty_bitmap_unlock(job->dirty_bitmap);
            break;
@@ -1259,9 +1257,10 @@ do_sync_target_write(MirrorBlockJob *job, MirrorMethod method,
                break;
            }
        }

        dirty_offset += dirty_bytes;
    }

    bdrv_dirty_iter_free(iter);
    if (qiov) {
        qemu_iovec_destroy(&target_qiov);
    }
+4 −3
Original line number Diff line number Diff line
@@ -83,8 +83,6 @@ void bdrv_set_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap,
void bdrv_reset_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap,
                                    int64_t offset, int64_t bytes);
int64_t bdrv_dirty_iter_next(BdrvDirtyBitmapIter *iter);
bool bdrv_dirty_iter_next_area(BdrvDirtyBitmapIter *iter, uint64_t max_offset,
                               uint64_t *offset, int *bytes);
void bdrv_set_dirty_iter(BdrvDirtyBitmapIter *hbi, int64_t offset);
int64_t bdrv_get_dirty_count(BdrvDirtyBitmap *bitmap);
int64_t bdrv_get_meta_dirty_count(BdrvDirtyBitmap *bitmap);
@@ -99,7 +97,10 @@ 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);
int64_t bdrv_dirty_bitmap_next_zero(BdrvDirtyBitmap *bitmap, uint64_t offset,
                                    uint64_t bytes);
bool bdrv_dirty_bitmap_next_dirty_area(BdrvDirtyBitmap *bitmap,
                                       uint64_t *offset, uint64_t *bytes);
BdrvDirtyBitmap *bdrv_reclaim_dirty_bitmap_locked(BlockDriverState *bs,
                                                  BdrvDirtyBitmap *bitmap,
                                                  Error **errp);
+24 −7
Original line number Diff line number Diff line
@@ -300,12 +300,32 @@ void hbitmap_iter_init(HBitmapIter *hbi, const HBitmap *hb, uint64_t first);
unsigned long hbitmap_iter_skip_words(HBitmapIter *hbi);

/* hbitmap_next_zero:
 *
 * Find next not dirty bit within selected range. If not found, return -1.
 *
 * @hb: The HBitmap to operate on
 * @start: The bit to start from.
 * @count: Number of bits to proceed. If @start+@count > bitmap size, the whole
 * bitmap is looked through. You can use UINT64_MAX as @count to search up to
 * the bitmap end.
 */
int64_t hbitmap_next_zero(const HBitmap *hb, uint64_t start, uint64_t count);

/* hbitmap_next_dirty_area:
 * @hb: The HBitmap to operate on
 * @start: in-out parameter.
 *         in: the offset to start from
 *         out: (if area found) start of found area
 * @count: in-out parameter.
 *         in: length of requested region
 *         out: length of found area
 *
 * Find next not dirty bit.
 * If dirty area found within [@start, @start + @count), returns true and sets
 * @offset and @bytes appropriately. Otherwise returns false and leaves @offset
 * and @bytes unchanged.
 */
int64_t hbitmap_next_zero(const HBitmap *hb, uint64_t start);
bool hbitmap_next_dirty_area(const HBitmap *hb, uint64_t *start,
                             uint64_t *count);

/* hbitmap_create_meta:
 * Create a "meta" hbitmap to track dirtiness of the bits in this HBitmap.
@@ -331,14 +351,11 @@ void hbitmap_free_meta(HBitmap *hb);
/**
 * hbitmap_iter_next:
 * @hbi: HBitmapIter to operate on.
 * @advance: If true, advance the iterator.  Otherwise, the next call
 *           of this function will return the same result (if that
 *           position is still dirty).
 *
 * Return the next bit that is set in @hbi's associated HBitmap,
 * or -1 if all remaining bits are zero.
 */
int64_t hbitmap_iter_next(HBitmapIter *hbi, bool advance);
int64_t hbitmap_iter_next(HBitmapIter *hbi);

/**
 * hbitmap_iter_next_word:
Loading