goto fail;
s->l1_table_offset = header.l1_table_offset;
s->l1_table = qemu_malloc(s->l1_size * sizeof(uint64_t));
- if (!s->l1_table)
- goto fail;
if (bdrv_pread(s->hd, s->l1_table_offset, s->l1_table, s->l1_size * sizeof(uint64_t)) !=
s->l1_size * sizeof(uint64_t))
goto fail;
}
/* alloc L2 cache */
s->l2_cache = qemu_malloc(s->l2_size * L2_CACHE_SIZE * sizeof(uint64_t));
- if (!s->l2_cache)
- goto fail;
s->cluster_cache = qemu_malloc(s->cluster_size);
- if (!s->cluster_cache)
- goto fail;
/* one more sector for decompressed data alignment */
s->cluster_data = qemu_malloc(QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size
+ 512);
- if (!s->cluster_data)
- goto fail;
s->cluster_cache_offset = -1;
if (refcount_init(bs) < 0)
new_l1_size2 = sizeof(uint64_t) * new_l1_size;
new_l1_table = qemu_mallocz(new_l1_size2);
- if (!new_l1_table)
- return -ENOMEM;
memcpy(new_l1_table, s->l1_table, s->l1_size * sizeof(uint64_t));
/* write new table (align to cluster) */
}
static int count_contiguous_clusters(uint64_t nb_clusters, int cluster_size,
- uint64_t *l2_table, uint64_t mask)
+ uint64_t *l2_table, uint64_t start, uint64_t mask)
{
int i;
uint64_t offset = be64_to_cpu(l2_table[0]) & ~mask;
- for (i = 0; i < nb_clusters; i++)
+ if (!offset)
+ return 0;
+
+ for (i = start; i < start + nb_clusters; i++)
if (offset + i * cluster_size != (be64_to_cpu(l2_table[i]) & ~mask))
break;
- return i;
+ return (i - start);
}
static int count_contiguous_free_clusters(uint64_t nb_clusters, uint64_t *l2_table)
} else {
/* how many allocated clusters ? */
c = count_contiguous_clusters(nb_clusters, s->cluster_size,
- &l2_table[l2_index], QCOW_OFLAG_COPIED);
+ &l2_table[l2_index], 0, QCOW_OFLAG_COPIED);
}
nb_available = (c * s->cluster_sectors);
if (m->nb_clusters == 0)
return 0;
- if (!(old_cluster = qemu_malloc(m->nb_clusters * sizeof(uint64_t))))
- return -ENOMEM;
+ old_cluster = qemu_malloc(m->nb_clusters * sizeof(uint64_t));
/* copy content of unmodified sectors */
start_sect = (m->offset & ~(s->cluster_size - 1)) >> 9;
if (cluster_offset & QCOW_OFLAG_COPIED) {
nb_clusters = count_contiguous_clusters(nb_clusters, s->cluster_size,
- &l2_table[l2_index], 0);
+ &l2_table[l2_index], 0, 0);
cluster_offset &= ~QCOW_OFLAG_COPIED;
m->nb_clusters = 0;
/* how many available clusters ? */
while (i < nb_clusters) {
+ i += count_contiguous_clusters(nb_clusters - i, s->cluster_size,
+ &l2_table[l2_index], i, 0);
+
+ if(be64_to_cpu(l2_table[l2_index + i]))
+ break;
+
i += count_contiguous_free_clusters(nb_clusters - i,
&l2_table[l2_index + i]);
if ((cluster_offset & QCOW_OFLAG_COPIED) ||
(cluster_offset & QCOW_OFLAG_COMPRESSED))
break;
-
- i += count_contiguous_clusters(nb_clusters - i, s->cluster_size,
- &l2_table[l2_index + i], 0);
-
- if(be64_to_cpu(l2_table[l2_index + i]))
- break;
}
nb_clusters = i;
if (!acb->cluster_data) {
acb->cluster_data = qemu_mallocz(QCOW_MAX_CRYPT_CLUSTERS *
s->cluster_size);
- if (!acb->cluster_data) {
- ret = -ENOMEM;
- goto fail;
- }
}
encrypt_sectors(s, acb->sector_num, acb->cluster_data, acb->buf,
acb->n, 1, &s->aes_encrypt_key);
offset += align_offset(l1_size * sizeof(uint64_t), s->cluster_size);
s->refcount_table = qemu_mallocz(s->cluster_size);
- if (!s->refcount_table)
- goto fail;
s->refcount_block = qemu_mallocz(s->cluster_size);
- if (!s->refcount_block)
- goto fail;
s->refcount_table_offset = offset;
header.refcount_table_offset = cpu_to_be64(offset);
qemu_free(s->refcount_block);
close(fd);
return 0;
- fail:
- qemu_free(s->refcount_table);
- qemu_free(s->refcount_block);
- close(fd);
- return -ENOMEM;
}
static int qcow_make_empty(BlockDriverState *bs)
return -EINVAL;
out_buf = qemu_malloc(s->cluster_size + (s->cluster_size / 1000) + 128);
- if (!out_buf)
- return -ENOMEM;
/* best compression, small window, no zlib header */
memset(&strm, 0, sizeof(strm));
l1_allocated = 0;
if (l1_table_offset != s->l1_table_offset) {
l1_table = qemu_malloc(l1_size2);
- if (!l1_table)
- goto fail;
l1_allocated = 1;
if (bdrv_pread(s->hd, l1_table_offset,
l1_table, l1_size2) != l1_size2)
l2_size = s->l2_size * sizeof(uint64_t);
l2_table = qemu_malloc(l2_size);
- if (!l2_table)
- goto fail;
l1_modified = 0;
for(i = 0; i < l1_size; i++) {
l2_offset = l1_table[i];
int64_t offset;
uint32_t extra_data_size;
+ if (!s->nb_snapshots) {
+ s->snapshots = NULL;
+ s->snapshots_size = 0;
+ return 0;
+ }
+
offset = s->snapshots_offset;
s->snapshots = qemu_mallocz(s->nb_snapshots * sizeof(QCowSnapshot));
- if (!s->snapshots)
- goto fail;
for(i = 0; i < s->nb_snapshots; i++) {
offset = align_offset(offset, 8);
if (bdrv_pread(s->hd, offset, &h, sizeof(h)) != sizeof(h))
offset += extra_data_size;
sn->id_str = qemu_malloc(id_str_size + 1);
- if (!sn->id_str)
- goto fail;
if (bdrv_pread(s->hd, offset, sn->id_str, id_str_size) != id_str_size)
goto fail;
offset += id_str_size;
sn->id_str[id_str_size] = '\0';
sn->name = qemu_malloc(name_size + 1);
- if (!sn->name)
- goto fail;
if (bdrv_pread(s->hd, offset, sn->name, name_size) != name_size)
goto fail;
offset += name_size;
sn->l1_size = s->l1_size;
l1_table = qemu_malloc(s->l1_size * sizeof(uint64_t));
- if (!l1_table)
- goto fail;
for(i = 0; i < s->l1_size; i++) {
l1_table[i] = cpu_to_be64(s->l1_table[i]);
}
l1_table = NULL;
snapshots1 = qemu_malloc((s->nb_snapshots + 1) * sizeof(QCowSnapshot));
- if (!snapshots1)
- goto fail;
- memcpy(snapshots1, s->snapshots, s->nb_snapshots * sizeof(QCowSnapshot));
+ if (s->snapshots) {
+ memcpy(snapshots1, s->snapshots, s->nb_snapshots * sizeof(QCowSnapshot));
+ qemu_free(s->snapshots);
+ }
s->snapshots = snapshots1;
s->snapshots[s->nb_snapshots++] = *sn;
int i;
sn_tab = qemu_mallocz(s->nb_snapshots * sizeof(QEMUSnapshotInfo));
- if (!sn_tab)
- goto fail;
for(i = 0; i < s->nb_snapshots; i++) {
sn_info = sn_tab + i;
sn = s->snapshots + i;
}
*psn_tab = sn_tab;
return s->nb_snapshots;
- fail:
- qemu_free(sn_tab);
- *psn_tab = NULL;
- return -ENOMEM;
}
/*********************************************************/
int ret, refcount_table_size2, i;
s->refcount_block_cache = qemu_malloc(s->cluster_size);
- if (!s->refcount_block_cache)
- goto fail;
refcount_table_size2 = s->refcount_table_size * sizeof(uint64_t);
s->refcount_table = qemu_malloc(refcount_table_size2);
- if (!s->refcount_table)
- goto fail;
if (s->refcount_table_size > 0) {
ret = bdrv_pread(s->hd, s->refcount_table_offset,
s->refcount_table, refcount_table_size2);
#endif
new_table_size2 = new_table_size * sizeof(uint64_t);
new_table = qemu_mallocz(new_table_size2);
- if (!new_table)
- return -ENOMEM;
memcpy(new_table, s->refcount_table,
s->refcount_table_size * sizeof(uint64_t));
for(i = 0; i < s->refcount_table_size; i++)
l1_table_offset, l1_size2);
l1_table = qemu_malloc(l1_size2);
- if (!l1_table)
- goto fail;
if (bdrv_pread(s->hd, l1_table_offset,
l1_table, l1_size2) != l1_size2)
goto fail;
l2_size = s->l2_size * sizeof(uint64_t);
l2_table = qemu_malloc(l2_size);
- if (!l2_table)
- goto fail;
for(i = 0; i < l1_size; i++) {
l2_offset = l1_table[i];
if (l2_offset) {
#endif
BlockDriver bdrv_qcow2 = {
- "qcow2",
- sizeof(BDRVQcowState),
- qcow_probe,
- qcow_open,
- NULL,
- NULL,
- qcow_close,
- qcow_create,
- qcow_flush,
- qcow_is_allocated,
- qcow_set_key,
- qcow_make_empty,
-
- .bdrv_aio_read = qcow_aio_read,
- .bdrv_aio_write = qcow_aio_write,
- .bdrv_aio_cancel = qcow_aio_cancel,
- .aiocb_size = sizeof(QCowAIOCB),
+ .format_name = "qcow2",
+ .instance_size = sizeof(BDRVQcowState),
+ .bdrv_probe = qcow_probe,
+ .bdrv_open = qcow_open,
+ .bdrv_close = qcow_close,
+ .bdrv_create = qcow_create,
+ .bdrv_flush = qcow_flush,
+ .bdrv_is_allocated = qcow_is_allocated,
+ .bdrv_set_key = qcow_set_key,
+ .bdrv_make_empty = qcow_make_empty,
+
+ .bdrv_aio_read = qcow_aio_read,
+ .bdrv_aio_write = qcow_aio_write,
+ .bdrv_aio_cancel = qcow_aio_cancel,
+ .aiocb_size = sizeof(QCowAIOCB),
.bdrv_write_compressed = qcow_write_compressed,
.bdrv_snapshot_create = qcow_snapshot_create,
- .bdrv_snapshot_goto = qcow_snapshot_goto,
+ .bdrv_snapshot_goto = qcow_snapshot_goto,
.bdrv_snapshot_delete = qcow_snapshot_delete,
- .bdrv_snapshot_list = qcow_snapshot_list,
- .bdrv_get_info = qcow_get_info,
+ .bdrv_snapshot_list = qcow_snapshot_list,
+ .bdrv_get_info = qcow_get_info,
};