Revision 3b46e624 block-qcow2.c
b/block-qcow2.c | ||
---|---|---|
37 | 37 |
- Size of compressed clusters is stored in sectors to reduce bit usage |
38 | 38 |
in the cluster offsets. |
39 | 39 |
- Support for storing additional data (such as the VM state) in the |
40 |
snapshots.
|
|
40 |
snapshots. |
|
41 | 41 |
- If a backing store is used, the cluster size is not constrained |
42 | 42 |
(could be backported to QCOW). |
43 | 43 |
- L2 tables have always a size of one cluster. |
... | ... | |
176 | 176 |
static int qcow_probe(const uint8_t *buf, int buf_size, const char *filename) |
177 | 177 |
{ |
178 | 178 |
const QCowHeader *cow_header = (const void *)buf; |
179 |
|
|
179 |
|
|
180 | 180 |
if (buf_size >= sizeof(QCowHeader) && |
181 | 181 |
be32_to_cpu(cow_header->magic) == QCOW_MAGIC && |
182 | 182 |
be32_to_cpu(cow_header->version) == QCOW_VERSION) |
... | ... | |
209 | 209 |
be32_to_cpus(&header.refcount_table_clusters); |
210 | 210 |
be64_to_cpus(&header.snapshots_offset); |
211 | 211 |
be32_to_cpus(&header.nb_snapshots); |
212 |
|
|
212 |
|
|
213 | 213 |
if (header.magic != QCOW_MAGIC || header.version != QCOW_VERSION) |
214 | 214 |
goto fail; |
215 | 215 |
if (header.size <= 1 || |
... | ... | |
267 | 267 |
if (!s->cluster_data) |
268 | 268 |
goto fail; |
269 | 269 |
s->cluster_cache_offset = -1; |
270 |
|
|
270 |
|
|
271 | 271 |
if (refcount_init(bs) < 0) |
272 | 272 |
goto fail; |
273 | 273 |
|
... | ... | |
304 | 304 |
BDRVQcowState *s = bs->opaque; |
305 | 305 |
uint8_t keybuf[16]; |
306 | 306 |
int len, i; |
307 |
|
|
307 |
|
|
308 | 308 |
memset(keybuf, 0, 16); |
309 | 309 |
len = strlen(key); |
310 | 310 |
if (len > 16) |
... | ... | |
451 | 451 |
|
452 | 452 |
/* write new table (align to cluster) */ |
453 | 453 |
new_l1_table_offset = alloc_clusters(bs, new_l1_size2); |
454 |
|
|
454 |
|
|
455 | 455 |
for(i = 0; i < s->l1_size; i++) |
456 | 456 |
new_l1_table[i] = cpu_to_be64(new_l1_table[i]); |
457 | 457 |
ret = bdrv_pwrite(s->hd, new_l1_table_offset, new_l1_table, new_l1_size2); |
... | ... | |
459 | 459 |
goto fail; |
460 | 460 |
for(i = 0; i < s->l1_size; i++) |
461 | 461 |
new_l1_table[i] = be64_to_cpu(new_l1_table[i]); |
462 |
|
|
462 |
|
|
463 | 463 |
/* set new table */ |
464 | 464 |
data64 = cpu_to_be64(new_l1_table_offset); |
465 | 465 |
if (bdrv_pwrite(s->hd, offsetof(QCowHeader, l1_table_offset), |
... | ... | |
501 | 501 |
BDRVQcowState *s = bs->opaque; |
502 | 502 |
int min_index, i, j, l1_index, l2_index, ret; |
503 | 503 |
uint64_t l2_offset, *l2_table, cluster_offset, tmp, old_l2_offset; |
504 |
|
|
504 |
|
|
505 | 505 |
l1_index = offset >> (s->l2_bits + s->cluster_bits); |
506 | 506 |
if (l1_index >= s->l1_size) { |
507 | 507 |
/* outside l1 table is allowed: we grow the table if needed */ |
... | ... | |
600 | 600 |
written */ |
601 | 601 |
if ((n_end - n_start) < s->cluster_sectors) { |
602 | 602 |
uint64_t start_sect; |
603 |
|
|
603 |
|
|
604 | 604 |
start_sect = (offset & ~(s->cluster_size - 1)) >> 9; |
605 | 605 |
ret = copy_sectors(bs, start_sect, |
606 | 606 |
cluster_offset, 0, n_start); |
... | ... | |
672 | 672 |
inflateEnd(strm); |
673 | 673 |
return 0; |
674 | 674 |
} |
675 |
|
|
675 |
|
|
676 | 676 |
static int decompress_cluster(BDRVQcowState *s, uint64_t cluster_offset) |
677 | 677 |
{ |
678 | 678 |
int ret, csize, nb_csectors, sector_offset; |
... | ... | |
717 | 717 |
BDRVQcowState *s = bs->opaque; |
718 | 718 |
int ret, index_in_cluster, n, n1; |
719 | 719 |
uint64_t cluster_offset; |
720 |
|
|
720 |
|
|
721 | 721 |
while (nb_sectors > 0) { |
722 | 722 |
cluster_offset = get_cluster_offset(bs, sector_num << 9, 0, 0, 0, 0); |
723 | 723 |
index_in_cluster = sector_num & (s->cluster_sectors - 1); |
... | ... | |
762 | 762 |
BDRVQcowState *s = bs->opaque; |
763 | 763 |
int ret, index_in_cluster, n; |
764 | 764 |
uint64_t cluster_offset; |
765 |
|
|
765 |
|
|
766 | 766 |
while (nb_sectors > 0) { |
767 | 767 |
index_in_cluster = sector_num & (s->cluster_sectors - 1); |
768 | 768 |
n = s->cluster_sectors - index_in_cluster; |
... | ... | |
841 | 841 |
qemu_aio_release(acb); |
842 | 842 |
return; |
843 | 843 |
} |
844 |
|
|
844 |
|
|
845 | 845 |
/* prepare next AIO request */ |
846 | 846 |
acb->cluster_offset = get_cluster_offset(bs, acb->sector_num << 9, |
847 | 847 |
0, 0, 0, 0); |
... | ... | |
948 | 948 |
qemu_aio_release(acb); |
949 | 949 |
return; |
950 | 950 |
} |
951 |
|
|
951 |
|
|
952 | 952 |
index_in_cluster = acb->sector_num & (s->cluster_sectors - 1); |
953 | 953 |
acb->n = s->cluster_sectors - index_in_cluster; |
954 | 954 |
if (acb->n > acb->nb_sectors) |
... | ... | |
988 | 988 |
{ |
989 | 989 |
BDRVQcowState *s = bs->opaque; |
990 | 990 |
QCowAIOCB *acb; |
991 |
|
|
991 |
|
|
992 | 992 |
s->cluster_cache_offset = -1; /* disable compressed cache */ |
993 | 993 |
|
994 | 994 |
acb = qcow_aio_setup(bs, sector_num, (uint8_t*)buf, nb_sectors, cb, opaque); |
995 | 995 |
if (!acb) |
996 | 996 |
return NULL; |
997 |
|
|
997 |
|
|
998 | 998 |
qcow_aio_write_cb(acb, 0); |
999 | 999 |
return &acb->common; |
1000 | 1000 |
} |
... | ... | |
1054 | 1054 |
QCowHeader header; |
1055 | 1055 |
uint64_t tmp, offset; |
1056 | 1056 |
QCowCreateState s1, *s = &s1; |
1057 |
|
|
1057 |
|
|
1058 | 1058 |
memset(s, 0, sizeof(*s)); |
1059 | 1059 |
|
1060 | 1060 |
fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644); |
... | ... | |
1096 | 1096 |
s->refcount_block = qemu_mallocz(s->cluster_size); |
1097 | 1097 |
if (!s->refcount_block) |
1098 | 1098 |
goto fail; |
1099 |
|
|
1099 |
|
|
1100 | 1100 |
s->refcount_table_offset = offset; |
1101 | 1101 |
header.refcount_table_offset = cpu_to_be64(offset); |
1102 | 1102 |
header.refcount_table_clusters = cpu_to_be32(1); |
... | ... | |
1111 | 1111 |
create_refcount_update(s, s->l1_table_offset, l1_size * sizeof(uint64_t)); |
1112 | 1112 |
create_refcount_update(s, s->refcount_table_offset, s->cluster_size); |
1113 | 1113 |
create_refcount_update(s, s->refcount_block_offset, s->cluster_size); |
1114 |
|
|
1114 |
|
|
1115 | 1115 |
/* write all the data */ |
1116 | 1116 |
write(fd, &header, sizeof(header)); |
1117 | 1117 |
if (backing_file) { |
... | ... | |
1124 | 1124 |
} |
1125 | 1125 |
lseek(fd, s->refcount_table_offset, SEEK_SET); |
1126 | 1126 |
write(fd, s->refcount_table, s->cluster_size); |
1127 |
|
|
1127 |
|
|
1128 | 1128 |
lseek(fd, s->refcount_block_offset, SEEK_SET); |
1129 | 1129 |
write(fd, s->refcount_block, s->cluster_size); |
1130 | 1130 |
|
... | ... | |
1153 | 1153 |
ret = bdrv_truncate(s->hd, s->l1_table_offset + l1_length); |
1154 | 1154 |
if (ret < 0) |
1155 | 1155 |
return ret; |
1156 |
|
|
1156 |
|
|
1157 | 1157 |
l2_cache_reset(bs); |
1158 | 1158 |
#endif |
1159 | 1159 |
return 0; |
... | ... | |
1223 | 1223 |
return -1; |
1224 | 1224 |
} |
1225 | 1225 |
} |
1226 |
|
|
1226 |
|
|
1227 | 1227 |
qemu_free(out_buf); |
1228 | 1228 |
return 0; |
1229 | 1229 |
} |
... | ... | |
1256 | 1256 |
uint64_t *l1_table, *l2_table, l2_offset, offset, l1_size2, l1_allocated; |
1257 | 1257 |
int64_t old_offset, old_l2_offset; |
1258 | 1258 |
int l2_size, i, j, l1_modified, l2_modified, nb_csectors, refcount; |
1259 |
|
|
1259 |
|
|
1260 | 1260 |
l2_cache_reset(bs); |
1261 | 1261 |
|
1262 | 1262 |
l2_table = NULL; |
... | ... | |
1278 | 1278 |
l1_table = s->l1_table; |
1279 | 1279 |
l1_allocated = 0; |
1280 | 1280 |
} |
1281 |
|
|
1281 |
|
|
1282 | 1282 |
l2_size = s->l2_size * sizeof(uint64_t); |
1283 | 1283 |
l2_table = qemu_malloc(l2_size); |
1284 | 1284 |
if (!l2_table) |
... | ... | |
1455 | 1455 |
|
1456 | 1456 |
snapshots_offset = alloc_clusters(bs, snapshots_size); |
1457 | 1457 |
offset = snapshots_offset; |
1458 |
|
|
1458 |
|
|
1459 | 1459 |
for(i = 0; i < s->nb_snapshots; i++) { |
1460 | 1460 |
sn = s->snapshots + i; |
1461 | 1461 |
memset(&h, 0, sizeof(h)); |
... | ... | |
1465 | 1465 |
h.date_sec = cpu_to_be32(sn->date_sec); |
1466 | 1466 |
h.date_nsec = cpu_to_be32(sn->date_nsec); |
1467 | 1467 |
h.vm_clock_nsec = cpu_to_be64(sn->vm_clock_nsec); |
1468 |
|
|
1468 |
|
|
1469 | 1469 |
id_str_size = strlen(sn->id_str); |
1470 | 1470 |
name_size = strlen(sn->name); |
1471 | 1471 |
h.id_str_size = cpu_to_be16(id_str_size); |
... | ... | |
1533 | 1533 |
{ |
1534 | 1534 |
BDRVQcowState *s = bs->opaque; |
1535 | 1535 |
int i, ret; |
1536 |
|
|
1536 |
|
|
1537 | 1537 |
ret = find_snapshot_by_id(bs, name); |
1538 | 1538 |
if (ret >= 0) |
1539 | 1539 |
return ret; |
... | ... | |
1552 | 1552 |
QCowSnapshot *snapshots1, sn1, *sn = &sn1; |
1553 | 1553 |
int i, ret; |
1554 | 1554 |
uint64_t *l1_table = NULL; |
1555 |
|
|
1555 |
|
|
1556 | 1556 |
memset(sn, 0, sizeof(*sn)); |
1557 | 1557 |
|
1558 | 1558 |
if (sn_info->id_str[0] == '\0') { |
... | ... | |
1663 | 1663 |
BDRVQcowState *s = bs->opaque; |
1664 | 1664 |
QCowSnapshot *sn; |
1665 | 1665 |
int snapshot_index, ret; |
1666 |
|
|
1666 |
|
|
1667 | 1667 |
snapshot_index = find_snapshot_by_id_or_name(bs, snapshot_id); |
1668 | 1668 |
if (snapshot_index < 0) |
1669 | 1669 |
return -ENOENT; |
... | ... | |
1731 | 1731 |
{ |
1732 | 1732 |
BDRVQcowState *s = bs->opaque; |
1733 | 1733 |
int ret, refcount_table_size2, i; |
1734 |
|
|
1734 |
|
|
1735 | 1735 |
s->refcount_block_cache = qemu_malloc(s->cluster_size); |
1736 | 1736 |
if (!s->refcount_block_cache) |
1737 | 1737 |
goto fail; |
... | ... | |
1839 | 1839 |
BDRVQcowState *s = bs->opaque; |
1840 | 1840 |
int64_t offset, cluster_offset; |
1841 | 1841 |
int free_in_cluster; |
1842 |
|
|
1842 |
|
|
1843 | 1843 |
assert(size > 0 && size <= s->cluster_size); |
1844 | 1844 |
if (s->free_byte_offset == 0) { |
1845 | 1845 |
s->free_byte_offset = alloc_clusters(bs, s->cluster_size); |
... | ... | |
2043 | 2043 |
BDRVQcowState *s = bs->opaque; |
2044 | 2044 |
int64_t start, last, cluster_offset; |
2045 | 2045 |
int k; |
2046 |
|
|
2046 |
|
|
2047 | 2047 |
if (size <= 0) |
2048 | 2048 |
return; |
2049 | 2049 |
|
... | ... | |
2086 | 2086 |
goto fail; |
2087 | 2087 |
for(i = 0;i < l1_size; i++) |
2088 | 2088 |
be64_to_cpus(&l1_table[i]); |
2089 |
|
|
2089 |
|
|
2090 | 2090 |
l2_size = s->l2_size * sizeof(uint64_t); |
2091 | 2091 |
l2_table = qemu_malloc(l2_size); |
2092 | 2092 |
if (!l2_table) |
... | ... | |
2165 | 2165 |
/* header */ |
2166 | 2166 |
inc_refcounts(bs, refcount_table, nb_clusters, |
2167 | 2167 |
0, s->cluster_size); |
2168 |
|
|
2168 |
|
|
2169 | 2169 |
check_refcounts_l1(bs, refcount_table, nb_clusters, |
2170 | 2170 |
s->l1_table_offset, s->l1_size, 1); |
2171 | 2171 |
|
Also available in: Unified diff