static BdrvDirtyBitmap *load_bitmap(BlockDriverState *bs, Qcow2Bitmap *bm, Error **errp) { int ret; uint64_t *bitmap_table = NULL; uint32_t granularity; BdrvDirtyBitmap *bitmap = NULL; if (bm->flags & BME_FLAG_IN_USE) { error_setg(errp, "Bitmap '%s' is in use", bm->name); goto fail; } ret = bitmap_table_load(bs, &bm->table, &bitmap_table); if (ret < 0) { error_setg_errno(errp, -ret, "Could not read bitmap_table table from image for " "bitmap '%s'", bm->name); goto fail; } granularity = 1U << bm->granularity_bits; bitmap = bdrv_create_dirty_bitmap(bs, granularity, bm->name, errp); if (bitmap == NULL) { goto fail; } ret = load_bitmap_data(bs, bitmap_table, bm->table.size, bitmap); if (ret < 0) { error_setg_errno(errp, -ret, "Could not read bitmap '%s' from image", bm->name); goto fail; } g_free(bitmap_table); return bitmap; fail: g_free(bitmap_table); if (bitmap != NULL) { bdrv_release_dirty_bitmap(bs, bitmap); } return NULL; }
static int free_bitmap_clusters(BlockDriverState *bs, Qcow2BitmapTable *tb) { int ret; uint64_t *bitmap_table; ret = bitmap_table_load(bs, tb, &bitmap_table); if (ret < 0) { return ret; } clear_bitmap_table(bs, bitmap_table, tb->size); qcow2_free_clusters(bs, tb->offset, tb->size * sizeof(uint64_t), QCOW2_DISCARD_OTHER); g_free(bitmap_table); tb->offset = 0; tb->size = 0; return 0; }
int qcow2_check_bitmaps_refcounts(BlockDriverState *bs, BdrvCheckResult *res, void **refcount_table, int64_t *refcount_table_size) { int ret; BDRVQcow2State *s = bs->opaque; Qcow2BitmapList *bm_list; Qcow2Bitmap *bm; if (s->nb_bitmaps == 0) { return 0; } ret = qcow2_inc_refcounts_imrt(bs, res, refcount_table, refcount_table_size, s->bitmap_directory_offset, s->bitmap_directory_size); if (ret < 0) { return ret; } bm_list = bitmap_list_load(bs, s->bitmap_directory_offset, s->bitmap_directory_size, NULL); if (bm_list == NULL) { res->corruptions++; return -EINVAL; } QSIMPLEQ_FOREACH(bm, bm_list, entry) { uint64_t *bitmap_table = NULL; int i; ret = qcow2_inc_refcounts_imrt(bs, res, refcount_table, refcount_table_size, bm->table.offset, bm->table.size * sizeof(uint64_t)); if (ret < 0) { goto out; } ret = bitmap_table_load(bs, &bm->table, &bitmap_table); if (ret < 0) { res->corruptions++; goto out; } for (i = 0; i < bm->table.size; ++i) { uint64_t entry = bitmap_table[i]; uint64_t offset = entry & BME_TABLE_ENTRY_OFFSET_MASK; if (check_table_entry(entry, s->cluster_size) < 0) { res->corruptions++; continue; } if (offset == 0) { continue; } ret = qcow2_inc_refcounts_imrt(bs, res, refcount_table, refcount_table_size, offset, s->cluster_size); if (ret < 0) { g_free(bitmap_table); goto out; } } g_free(bitmap_table); }