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

dirty-bitmap: add bdrv_dirty_bitmap_next_dirty_area



The function alters bdrv_dirty_iter_next_area(), which is wrong and
less efficient (see further commit
"block/mirror: fix and improve do_sync_target_write" for description).

Signed-off-by: default avatarVladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
parent fa9c2da2
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -787,6 +787,12 @@ int64_t bdrv_dirty_bitmap_next_zero(BdrvDirtyBitmap *bitmap, uint64_t offset,
    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_dirty_area(bitmap->bitmap, offset, bytes);
}

void bdrv_merge_dirty_bitmap(BdrvDirtyBitmap *dest, const BdrvDirtyBitmap *src,
                             HBitmap **backup, Error **errp)
{
+2 −0
Original line number Diff line number Diff line
@@ -101,6 +101,8 @@ BdrvDirtyBitmap *bdrv_dirty_bitmap_next(BlockDriverState *bs,
char *bdrv_dirty_bitmap_sha256(const BdrvDirtyBitmap *bitmap, Error **errp);
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);
+16 −0
Original line number Diff line number Diff line
@@ -311,6 +311,22 @@ unsigned long hbitmap_iter_skip_words(HBitmapIter *hbi);
 */
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
 *
 * 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.
 */
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.
 * The caller owns the created bitmap and must call hbitmap_free_meta(hb) to
+39 −0
Original line number Diff line number Diff line
@@ -246,6 +246,45 @@ int64_t hbitmap_next_zero(const HBitmap *hb, uint64_t start, uint64_t count)
    return res;
}

bool hbitmap_next_dirty_area(const HBitmap *hb, uint64_t *start,
                             uint64_t *count)
{
    HBitmapIter hbi;
    int64_t firt_dirty_off, area_end;
    uint32_t granularity = 1UL << hb->granularity;
    uint64_t end;

    if (*start >= hb->orig_size || *count == 0) {
        return false;
    }

    end = *count > hb->orig_size - *start ? hb->orig_size : *start + *count;

    hbitmap_iter_init(&hbi, hb, *start);
    firt_dirty_off = hbitmap_iter_next(&hbi, false);

    if (firt_dirty_off < 0 || firt_dirty_off >= end) {
        return false;
    }

    if (firt_dirty_off + granularity >= end) {
        area_end = end;
    } else {
        area_end = hbitmap_next_zero(hb, firt_dirty_off + granularity,
                                     end - firt_dirty_off - granularity);
        if (area_end < 0) {
            area_end = end;
        }
    }

    if (firt_dirty_off > *start) {
        *start = firt_dirty_off;
    }
    *count = area_end - *start;

    return true;
}

bool hbitmap_empty(const HBitmap *hb)
{
    return hb->count == 0;