Message ID | 20170913181910.29688-13-mreitz@redhat.com |
---|---|
State | New |
Headers | show |
Series | block/mirror: Add active-sync mirroring | expand |
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 <mreitz@redhat.com> > --- > 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(&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. > + */ > +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(&iter->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(&iter->hbi, true); > + size += granularity; > + } while ((ret << BDRV_SECTOR_BITS) + granularity <= gran_max_offset && > + hbitmap_iter_next(&iter->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)
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
25.09.2017 18: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 there is a mistake in this hbitmap_next_zero, I'll send today corrected version as part of small backup-related series. > > 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 <mreitz@redhat.com> >> --- >> 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(&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. >> + */ >> +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(&iter->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(&iter->hbi, true); >> + size += granularity; >> + } while ((ret << BDRV_SECTOR_BITS) + granularity <= >> gran_max_offset && >> + hbitmap_iter_next(&iter->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
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(&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. + */ +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(&iter->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(&iter->hbi, true); + size += granularity; + } while ((ret << BDRV_SECTOR_BITS) + granularity <= gran_max_offset && + hbitmap_iter_next(&iter->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)
This new function allows to look for a consecutively dirty area in a dirty bitmap. Signed-off-by: Max Reitz <mreitz@redhat.com> --- include/block/dirty-bitmap.h | 2 ++ block/dirty-bitmap.c | 52 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+)