int qcow2_expand_zero_clusters(BlockDriverState *bs) { BDRVQcowState *s = bs->opaque; uint64_t *l1_table = NULL; uint64_t nb_clusters; uint8_t *expanded_clusters; int ret; int i, j; nb_clusters = size_to_clusters(s, bs->file->total_sectors * BDRV_SECTOR_SIZE); expanded_clusters = g_malloc0((nb_clusters + 7) / 8); ret = expand_zero_clusters_in_l1(bs, s->l1_table, s->l1_size, &expanded_clusters, &nb_clusters); if (ret < 0) { goto fail; } /* Inactive L1 tables may point to active L2 tables - therefore it is * necessary to flush the L2 table cache before trying to access the L2 * tables pointed to by inactive L1 entries (else we might try to expand * zero clusters that have already been expanded); furthermore, it is also * necessary to empty the L2 table cache, since it may contain tables which * are now going to be modified directly on disk, bypassing the cache. * qcow2_cache_empty() does both for us. */ ret = qcow2_cache_empty(bs, s->l2_table_cache); if (ret < 0) { goto fail; } for (i = 0; i < s->nb_snapshots; i++) { int l1_sectors = (s->snapshots[i].l1_size * sizeof(uint64_t) + BDRV_SECTOR_SIZE - 1) / BDRV_SECTOR_SIZE; l1_table = g_realloc(l1_table, l1_sectors * BDRV_SECTOR_SIZE); ret = bdrv_read(bs->file, s->snapshots[i].l1_table_offset / BDRV_SECTOR_SIZE, (void *)l1_table, l1_sectors); if (ret < 0) { goto fail; } for (j = 0; j < s->snapshots[i].l1_size; j++) { be64_to_cpus(&l1_table[j]); } ret = expand_zero_clusters_in_l1(bs, l1_table, s->snapshots[i].l1_size, &expanded_clusters, &nb_clusters); if (ret < 0) { goto fail; } } ret = 0; fail: g_free(expanded_clusters); g_free(l1_table); return ret; }