@@ -253,6 +253,62 @@ static int load_autoload_bitmaps(BlockDriverState *bs, Error **errp)
return 0;
}
+static int bitmap_table_load(BlockDriverState *bs, QCow2BitmapHeader *bmh,
+ uint64_t **table);
+int qcow2_dirty_bitmaps_refcounts(BlockDriverState *bs,
+ BdrvCheckResult *res,
+ void **refcount_table,
+ int64_t *refcount_table_size)
+{
+ BDRVQcow2State *s = bs->opaque;
+ QCow2BitmapHeader *h,
+ *begin = (QCow2BitmapHeader *)s->bitmap_directory,
+ *end = (QCow2BitmapHeader *)
+ (s->bitmap_directory + s->bitmap_directory_size);
+
+ int i;
+ int ret = inc_refcounts(bs, res, refcount_table, refcount_table_size,
+ s->bitmap_directory_offset,
+ s->bitmap_directory_size);
+ if (ret < 0) {
+ return ret;
+ }
+
+ for (h = begin; h < end; h = next_dir_entry(h)) {
+ uint64_t *bitmap_table = NULL;
+
+ ret = inc_refcounts(bs, res, refcount_table, refcount_table_size,
+ h->bitmap_table_offset,
+ h->bitmap_table_size);
+ if (ret < 0) {
+ return ret;
+ }
+
+ ret = bitmap_table_load(bs, h, &bitmap_table);
+ if (ret < 0) {
+ return ret;
+ }
+
+ for (i = 0; i < h->bitmap_table_size; ++i) {
+ uint64_t off = be64_to_cpu(bitmap_table[i]);
+ if (off <= 1) {
+ continue;
+ }
+
+ ret = inc_refcounts(bs, res, refcount_table, refcount_table_size,
+ off, s->cluster_size);
+ if (ret < 0) {
+ g_free(bitmap_table);
+ return ret;
+ }
+ }
+
+ g_free(bitmap_table);
+ }
+
+ return 0;
+}
+
static int handle_in_use_bitmaps(BlockDriverState *bs);
int qcow2_read_bitmaps(BlockDriverState *bs, Error **errp)
{
@@ -351,8 +407,6 @@ static void do_free_bitmap_clusters(BlockDriverState *bs,
QCOW2_DISCARD_ALWAYS);
}
-static int bitmap_table_load(BlockDriverState *bs, QCow2BitmapHeader *bmh,
- uint64_t **table);
static int free_bitmap_clusters(BlockDriverState *bs, QCow2BitmapHeader *bmh)
{
int ret;
@@ -1309,11 +1309,9 @@ static int realloc_refcount_array(BDRVQcow2State *s, void **array,
*
* Modifies the number of errors in res.
*/
-static int inc_refcounts(BlockDriverState *bs,
- BdrvCheckResult *res,
- void **refcount_table,
- int64_t *refcount_table_size,
- int64_t offset, int64_t size)
+int inc_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
+ void **refcount_table, int64_t *refcount_table_size,
+ int64_t offset, int64_t size)
{
BDRVQcow2State *s = bs->opaque;
uint64_t start, last, cluster_offset, k, refcount;
@@ -1843,6 +1841,12 @@ static int calculate_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
return ret;
}
+ /* dirty bitmaps */
+ ret = qcow2_dirty_bitmaps_refcounts(bs, res, refcount_table, nb_clusters);
+ if (ret < 0) {
+ return ret;
+ }
+
return check_refblocks(bs, res, fix, rebuild, refcount_table, nb_clusters);
}
@@ -564,6 +564,9 @@ int qcow2_check_metadata_overlap(BlockDriverState *bs, int ign, int64_t offset,
int64_t size);
int qcow2_pre_write_overlap_check(BlockDriverState *bs, int ign, int64_t offset,
int64_t size);
+int inc_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
+ void **refcount_table, int64_t *refcount_table_size,
+ int64_t offset, int64_t size);
int qcow2_change_refcount_order(BlockDriverState *bs, int refcount_order,
BlockDriverAmendStatusCB *status_cb,
@@ -623,6 +626,8 @@ BdrvDirtyBitmap *qcow2_bitmap_load(BlockDriverState *bs, const char *name,
void qcow2_bitmap_store(BlockDriverState *bs, BdrvDirtyBitmap *bitmap,
Error **errp);
int qcow2_delete_bitmaps(BlockDriverState *bs);
+int qcow2_dirty_bitmaps_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
+ void **refcount_table, int64_t *refcount_table_size);
/* qcow2-cache.c functions */
Qcow2Cache *qcow2_cache_create(BlockDriverState *bs, int num_tables);