From 36323c9384909d2213fafb77b1fcf0ddbfcaaffc Mon Sep 17 00:00:00 2001
From: John Snow <jsnow@redhat.com>
Date: Tue, 20 Nov 2018 18:18:09 +0000
Subject: [PATCH 15/35] block/dirty-bitmap: Add bdrv_dirty_iter_next_area
RH-Author: John Snow <jsnow@redhat.com>
Message-id: <20181120181828.15132-6-jsnow@redhat.com>
Patchwork-id: 83054
O-Subject: [RHEL8/rhel qemu-kvm PATCH 05/24] block/dirty-bitmap: Add bdrv_dirty_iter_next_area
Bugzilla: 1518989
RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
RH-Acked-by: Max Reitz <mreitz@redhat.com>
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
From: Max Reitz <mreitz@redhat.com>
This new function allows to look for a consecutively dirty area in a
dirty bitmap.
Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Fam Zheng <famz@redhat.com>
Reviewed-by: John Snow <jsnow@redhat.com>
Message-id: 20180613181823.13618-10-mreitz@redhat.com
Signed-off-by: Max Reitz <mreitz@redhat.com>
(cherry picked from commit 72d10a94213a954ad569095cb4491f2ae0853c40)
Signed-off-by: John Snow <jsnow@redhat.com>
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
---
block/dirty-bitmap.c | 55 ++++++++++++++++++++++++++++++++++++++++++++
include/block/dirty-bitmap.h | 2 ++
2 files changed, 57 insertions(+)
diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c
index 236dce1..c9b8a6f 100644
--- a/block/dirty-bitmap.c
+++ b/block/dirty-bitmap.c
@@ -528,6 +528,61 @@ 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;
+}
+
/* Called within bdrv_dirty_bitmap_lock..unlock */
void bdrv_set_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap,
int64_t offset, int64_t bytes)
diff --git a/include/block/dirty-bitmap.h b/include/block/dirty-bitmap.h
index bf68dd7..259bd27 100644
--- a/include/block/dirty-bitmap.h
+++ b/include/block/dirty-bitmap.h
@@ -83,6 +83,8 @@ 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);
--
1.8.3.1