int ret, refcount_table_size2, i;
refcount_table_size2 = s->refcount_table_size * sizeof(uint64_t);
- s->refcount_table = qemu_malloc(refcount_table_size2);
+ s->refcount_table = g_malloc(refcount_table_size2);
if (s->refcount_table_size > 0) {
BLKDBG_EVENT(bs->file, BLKDBG_REFTABLE_LOAD);
ret = bdrv_pread(bs->file, s->refcount_table_offset,
void qcow2_refcount_close(BlockDriverState *bs)
{
BDRVQcowState *s = bs->opaque;
- qemu_free(s->refcount_table);
+ g_free(s->refcount_table);
}
uint64_t meta_offset = (blocks_used * refcount_block_clusters) *
s->cluster_size;
uint64_t table_offset = meta_offset + blocks_clusters * s->cluster_size;
- uint16_t *new_blocks = qemu_mallocz(blocks_clusters * s->cluster_size);
- uint64_t *new_table = qemu_mallocz(table_size * sizeof(uint64_t));
+ uint16_t *new_blocks = g_malloc0(blocks_clusters * s->cluster_size);
+ uint64_t *new_table = g_malloc0(table_size * sizeof(uint64_t));
assert(meta_offset >= (s->free_cluster_index * s->cluster_size));
BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_ALLOC_WRITE_BLOCKS);
ret = bdrv_pwrite_sync(bs->file, meta_offset, new_blocks,
blocks_clusters * s->cluster_size);
- qemu_free(new_blocks);
+ g_free(new_blocks);
if (ret < 0) {
goto fail_table;
}
uint64_t old_table_offset = s->refcount_table_offset;
uint64_t old_table_size = s->refcount_table_size;
- qemu_free(s->refcount_table);
+ g_free(s->refcount_table);
s->refcount_table = new_table;
s->refcount_table_size = table_size;
s->refcount_table_offset = table_offset;
return new_block;
fail_table:
- qemu_free(new_table);
+ g_free(new_table);
fail_block:
if (*refcount_block != NULL) {
qcow2_cache_put(bs, s->refcount_block_cache, (void**) refcount_block);
int ret;
#ifdef DEBUG_ALLOC2
- printf("update_refcount: offset=%" PRId64 " size=%" PRId64 " addend=%d\n",
+ fprintf(stderr, "update_refcount: offset=%" PRId64 " size=%" PRId64 " addend=%d\n",
offset, length, addend);
#endif
if (length < 0) {
}
}
#ifdef DEBUG_ALLOC2
- printf("alloc_clusters: size=%" PRId64 " -> %" PRId64 "\n",
+ fprintf(stderr, "alloc_clusters: size=%" PRId64 " -> %" PRId64 "\n",
size,
(s->free_cluster_index - nb_clusters) << s->cluster_bits);
#endif
-void qcow2_create_refcount_update(QCowCreateState *s, int64_t offset,
- int64_t size)
-{
- int refcount;
- int64_t start, last, cluster_offset;
- uint16_t *p;
-
- start = offset & ~(s->cluster_size - 1);
- last = (offset + size - 1) & ~(s->cluster_size - 1);
- for(cluster_offset = start; cluster_offset <= last;
- cluster_offset += s->cluster_size) {
- p = &s->refcount_block[cluster_offset >> s->cluster_bits];
- refcount = be16_to_cpu(*p);
- refcount++;
- *p = cpu_to_be16(refcount);
- }
-}
-
/* update the refcounts of snapshots and the copied flag */
int qcow2_update_snapshot_refcount(BlockDriverState *bs,
int64_t l1_table_offset, int l1_size, int addend)
BDRVQcowState *s = bs->opaque;
uint64_t *l1_table, *l2_table, l2_offset, offset, l1_size2, l1_allocated;
int64_t old_offset, old_l2_offset;
- int i, j, l1_modified, nb_csectors, refcount;
+ int i, j, l1_modified = 0, nb_csectors, refcount;
int ret;
+ bool old_l2_writethrough, old_refcount_writethrough;
+
+ /* Switch caches to writeback mode during update */
+ old_l2_writethrough =
+ qcow2_cache_set_writethrough(bs, s->l2_table_cache, false);
+ old_refcount_writethrough =
+ qcow2_cache_set_writethrough(bs, s->refcount_block_cache, false);
l2_table = NULL;
l1_table = NULL;
l1_size2 = l1_size * sizeof(uint64_t);
if (l1_table_offset != s->l1_table_offset) {
if (l1_size2 != 0) {
- l1_table = qemu_mallocz(align_offset(l1_size2, 512));
+ l1_table = g_malloc0(align_offset(l1_size2, 512));
} else {
l1_table = NULL;
}
l1_allocated = 1;
if (bdrv_pread(bs->file, l1_table_offset,
l1_table, l1_size2) != l1_size2)
+ {
+ ret = -EIO;
goto fail;
+ }
+
for(i = 0;i < l1_size; i++)
be64_to_cpus(&l1_table[i]);
} else {
l1_allocated = 0;
}
- l1_modified = 0;
for(i = 0; i < l1_size; i++) {
l2_offset = l1_table[i];
if (l2_offset) {
}
if (refcount < 0) {
+ ret = -EIO;
goto fail;
}
}
refcount = get_refcount(bs, l2_offset >> s->cluster_bits);
}
if (refcount < 0) {
+ ret = -EIO;
goto fail;
} else if (refcount == 1) {
l2_offset |= QCOW_OFLAG_COPIED;
}
}
}
+
+ ret = 0;
+fail:
+ if (l2_table) {
+ qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);
+ }
+
+ /* Enable writethrough cache mode again */
+ qcow2_cache_set_writethrough(bs, s->l2_table_cache, old_l2_writethrough);
+ qcow2_cache_set_writethrough(bs, s->refcount_block_cache,
+ old_refcount_writethrough);
+
if (l1_modified) {
for(i = 0; i < l1_size; i++)
cpu_to_be64s(&l1_table[i]);
be64_to_cpus(&l1_table[i]);
}
if (l1_allocated)
- qemu_free(l1_table);
- return 0;
- fail:
- if (l2_table) {
- qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);
- }
-
- if (l1_allocated)
- qemu_free(l1_table);
- return -EIO;
+ g_free(l1_table);
+ return ret;
}
/* Read L2 table from disk */
l2_size = s->l2_size * sizeof(uint64_t);
- l2_table = qemu_malloc(l2_size);
+ l2_table = g_malloc(l2_size);
if (bdrv_pread(bs->file, l2_offset, l2_table, l2_size) != l2_size)
goto fail;
}
}
- qemu_free(l2_table);
+ g_free(l2_table);
return 0;
fail:
fprintf(stderr, "ERROR: I/O error in check_refcounts_l2\n");
- qemu_free(l2_table);
+ g_free(l2_table);
return -EIO;
}
if (l1_size2 == 0) {
l1_table = NULL;
} else {
- l1_table = qemu_malloc(l1_size2);
+ l1_table = g_malloc(l1_size2);
if (bdrv_pread(bs->file, l1_table_offset,
l1_table, l1_size2) != l1_size2)
goto fail;
}
}
}
- qemu_free(l1_table);
+ g_free(l1_table);
return 0;
fail:
fprintf(stderr, "ERROR: I/O error in check_refcounts_l1\n");
res->check_errors++;
- qemu_free(l1_table);
+ g_free(l1_table);
return -EIO;
}
size = bdrv_getlength(bs->file);
nb_clusters = size_to_clusters(s, size);
- refcount_table = qemu_mallocz(nb_clusters * sizeof(uint16_t));
+ refcount_table = g_malloc0(nb_clusters * sizeof(uint16_t));
/* header */
inc_refcounts(bs, res, refcount_table, nb_clusters,
ret = check_refcounts_l1(bs, res, refcount_table, nb_clusters,
s->l1_table_offset, s->l1_size, 1);
if (ret < 0) {
- return ret;
+ goto fail;
}
/* snapshots */
ret = check_refcounts_l1(bs, res, refcount_table, nb_clusters,
sn->l1_table_offset, sn->l1_size, 0);
if (ret < 0) {
- return ret;
+ goto fail;
}
}
inc_refcounts(bs, res, refcount_table, nb_clusters,
}
}
- qemu_free(refcount_table);
+ ret = 0;
- return 0;
+fail:
+ g_free(refcount_table);
+
+ return ret;
}