Re: [Qemu-devel] [PATCH 12/18] block/dirty-bitmap: Add bdrv_dirty_iter_next_area
On 2017-09-25 17:49, Vladimir Sementsov-Ogievskiy wrote: > I have a patch on list, which adds hbitmap_next_zero function, it may help > https://lists.nongnu.org/archive/html/qemu-devel/2017-02/msg00809.html Hmmm. Sounds good, but (1) I would need to directly access the bitmap instead of the iterator, and (2) I would still need to clear the whole in the iterator... It does sound tempting because I could drop the previous patch, then (and thus wouldn't have to worry about concurrent resetting), but I don't think the whole implementation would be simpler. I'll think about it, but thanks for pointing it out in any case! Max signature.asc Description: OpenPGP digital signature
Re: [Qemu-devel] [PATCH 12/18] block/dirty-bitmap: Add bdrv_dirty_iter_next_area
I have a patch on list, which adds hbitmap_next_zero function, it may help https://lists.nongnu.org/archive/html/qemu-devel/2017-02/msg00809.html 13.09.2017 21:19, Max Reitz wrote: This new function allows to look for a consecutively dirty area in a dirty bitmap. Signed-off-by: Max Reitz--- include/block/dirty-bitmap.h | 2 ++ block/dirty-bitmap.c | 52 2 files changed, 54 insertions(+) diff --git a/include/block/dirty-bitmap.h b/include/block/dirty-bitmap.h index a79a58d2c3..7654748700 100644 --- a/include/block/dirty-bitmap.h +++ b/include/block/dirty-bitmap.h @@ -90,6 +90,8 @@ void bdrv_set_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap, void bdrv_reset_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap, int64_t cur_sector, int64_t nr_sectors); 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 sector_num); int64_t bdrv_get_dirty_count(BdrvDirtyBitmap *bitmap); int64_t bdrv_get_meta_dirty_count(BdrvDirtyBitmap *bitmap); diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c index aee57cf8c8..81b2f78016 100644 --- a/block/dirty-bitmap.c +++ b/block/dirty-bitmap.c @@ -550,6 +550,58 @@ int64_t bdrv_dirty_iter_next(BdrvDirtyBitmapIter *iter) return hbitmap_iter_next(>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. + */ +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; +int sector_gran = granularity >> BDRV_SECTOR_BITS; +int64_t ret; +int size; + +if (DIV_ROUND_UP(max_offset, BDRV_SECTOR_SIZE) == 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(>hbi, false); +if (ret < 0 || (ret << BDRV_SECTOR_BITS) + granularity > gran_max_offset) { +return false; +} + +*offset = ret << BDRV_SECTOR_BITS; +size = 0; + +assert(granularity <= INT_MAX); + +do { +/* Advance iterator */ +ret = hbitmap_iter_next(>hbi, true); +size += granularity; +} while ((ret << BDRV_SECTOR_BITS) + granularity <= gran_max_offset && + hbitmap_iter_next(>hbi, false) == ret + sector_gran && + size <= INT_MAX - granularity); + +*bytes = MIN(size, max_offset - *offset); +return true; +} + /* Called within bdrv_dirty_bitmap_lock..unlock */ void bdrv_set_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap, int64_t cur_sector, int64_t nr_sectors) -- Best regards, Vladimir
[Qemu-devel] [PATCH 12/18] block/dirty-bitmap: Add bdrv_dirty_iter_next_area
This new function allows to look for a consecutively dirty area in a dirty bitmap. Signed-off-by: Max Reitz--- include/block/dirty-bitmap.h | 2 ++ block/dirty-bitmap.c | 52 2 files changed, 54 insertions(+) diff --git a/include/block/dirty-bitmap.h b/include/block/dirty-bitmap.h index a79a58d2c3..7654748700 100644 --- a/include/block/dirty-bitmap.h +++ b/include/block/dirty-bitmap.h @@ -90,6 +90,8 @@ void bdrv_set_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap, void bdrv_reset_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap, int64_t cur_sector, int64_t nr_sectors); 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 sector_num); int64_t bdrv_get_dirty_count(BdrvDirtyBitmap *bitmap); int64_t bdrv_get_meta_dirty_count(BdrvDirtyBitmap *bitmap); diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c index aee57cf8c8..81b2f78016 100644 --- a/block/dirty-bitmap.c +++ b/block/dirty-bitmap.c @@ -550,6 +550,58 @@ int64_t bdrv_dirty_iter_next(BdrvDirtyBitmapIter *iter) return hbitmap_iter_next(>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. + */ +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; +int sector_gran = granularity >> BDRV_SECTOR_BITS; +int64_t ret; +int size; + +if (DIV_ROUND_UP(max_offset, BDRV_SECTOR_SIZE) == 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(>hbi, false); +if (ret < 0 || (ret << BDRV_SECTOR_BITS) + granularity > gran_max_offset) { +return false; +} + +*offset = ret << BDRV_SECTOR_BITS; +size = 0; + +assert(granularity <= INT_MAX); + +do { +/* Advance iterator */ +ret = hbitmap_iter_next(>hbi, true); +size += granularity; +} while ((ret << BDRV_SECTOR_BITS) + granularity <= gran_max_offset && + hbitmap_iter_next(>hbi, false) == ret + sector_gran && + size <= INT_MAX - granularity); + +*bytes = MIN(size, max_offset - *offset); +return true; +} + /* Called within bdrv_dirty_bitmap_lock..unlock */ void bdrv_set_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap, int64_t cur_sector, int64_t nr_sectors) -- 2.13.5