aboutsummaryrefslogtreecommitdiff
path: root/block/qcow2-bitmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'block/qcow2-bitmap.c')
-rw-r--r--block/qcow2-bitmap.c36
1 files changed, 36 insertions, 0 deletions
diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
index 1cf6d2ab77..7bf12502da 100644
--- a/block/qcow2-bitmap.c
+++ b/block/qcow2-bitmap.c
@@ -1755,3 +1755,39 @@ bool qcow2_supports_persistent_dirty_bitmap(BlockDriverState *bs)
return s->qcow_version >= 3;
}
+
+/*
+ * Compute the space required for bitmaps in @bs.
+ *
+ * The computation is based as if copying to a new image with the
+ * given @cluster_size, which may differ from the cluster size in @bs.
+ */
+uint64_t qcow2_get_persistent_dirty_bitmap_size(BlockDriverState *bs,
+ uint32_t cluster_size)
+{
+ uint64_t bitmaps_size = 0;
+ BdrvDirtyBitmap *bm;
+ size_t bitmap_dir_size = 0;
+
+ FOR_EACH_DIRTY_BITMAP(bs, bm) {
+ if (bdrv_dirty_bitmap_get_persistence(bm)) {
+ const char *name = bdrv_dirty_bitmap_name(bm);
+ uint32_t granularity = bdrv_dirty_bitmap_granularity(bm);
+ uint64_t bmbytes =
+ get_bitmap_bytes_needed(bdrv_dirty_bitmap_size(bm),
+ granularity);
+ uint64_t bmclusters = DIV_ROUND_UP(bmbytes, cluster_size);
+
+ /* Assume the entire bitmap is allocated */
+ bitmaps_size += bmclusters * cluster_size;
+ /* Also reserve space for the bitmap table entries */
+ bitmaps_size += ROUND_UP(bmclusters * sizeof(uint64_t),
+ cluster_size);
+ /* And space for contribution to bitmap directory size */
+ bitmap_dir_size += calc_dir_entry_size(strlen(name), 0);
+ }
+ }
+ bitmaps_size += ROUND_UP(bitmap_dir_size, cluster_size);
+
+ return bitmaps_size;
+}