Revision 4768fa90
b/block/qcow2.c | ||
---|---|---|
850 | 850 |
{ |
851 | 851 |
|
852 | 852 |
int fd, header_size, backing_filename_len, l1_size, i, shift, l2_bits; |
853 |
int ref_clusters, backing_format_len = 0; |
|
853 |
int ref_clusters, reftable_clusters, backing_format_len = 0;
|
|
854 | 854 |
int rounded_ext_bf_len = 0; |
855 | 855 |
QCowHeader header; |
856 | 856 |
uint64_t tmp, offset; |
857 |
uint64_t old_ref_clusters; |
|
857 | 858 |
QCowCreateState s1, *s = &s1; |
858 | 859 |
QCowExtension ext_bf = {0, 0}; |
859 | 860 |
int ret; |
... | ... | |
912 | 913 |
header.l1_size = cpu_to_be32(l1_size); |
913 | 914 |
offset += align_offset(l1_size * sizeof(uint64_t), s->cluster_size); |
914 | 915 |
|
915 |
s->refcount_table = qemu_mallocz(s->cluster_size); |
|
916 |
/* count how many refcount blocks needed */ |
|
917 |
|
|
918 |
#define NUM_CLUSTERS(bytes) \ |
|
919 |
(((bytes) + (s->cluster_size) - 1) / (s->cluster_size)) |
|
920 |
|
|
921 |
ref_clusters = NUM_CLUSTERS(NUM_CLUSTERS(offset) * sizeof(uint16_t)); |
|
922 |
|
|
923 |
do { |
|
924 |
uint64_t image_clusters; |
|
925 |
old_ref_clusters = ref_clusters; |
|
926 |
|
|
927 |
/* Number of clusters used for the refcount table */ |
|
928 |
reftable_clusters = NUM_CLUSTERS(ref_clusters * sizeof(uint64_t)); |
|
929 |
|
|
930 |
/* Number of clusters that the whole image will have */ |
|
931 |
image_clusters = NUM_CLUSTERS(offset) + ref_clusters |
|
932 |
+ reftable_clusters; |
|
933 |
|
|
934 |
/* Number of refcount blocks needed for the image */ |
|
935 |
ref_clusters = NUM_CLUSTERS(image_clusters * sizeof(uint16_t)); |
|
936 |
|
|
937 |
} while (ref_clusters != old_ref_clusters); |
|
938 |
|
|
939 |
s->refcount_table = qemu_mallocz(reftable_clusters * s->cluster_size); |
|
916 | 940 |
|
917 | 941 |
s->refcount_table_offset = offset; |
918 | 942 |
header.refcount_table_offset = cpu_to_be64(offset); |
919 |
header.refcount_table_clusters = cpu_to_be32(1);
|
|
920 |
offset += s->cluster_size;
|
|
943 |
header.refcount_table_clusters = cpu_to_be32(reftable_clusters);
|
|
944 |
offset += (reftable_clusters * s->cluster_size);
|
|
921 | 945 |
s->refcount_block_offset = offset; |
922 | 946 |
|
923 |
/* count how many refcount blocks needed */ |
|
924 |
tmp = offset >> s->cluster_bits; |
|
925 |
ref_clusters = (tmp >> (s->cluster_bits - REFCOUNT_SHIFT)) + 1; |
|
926 | 947 |
for (i=0; i < ref_clusters; i++) { |
927 | 948 |
s->refcount_table[i] = cpu_to_be64(offset); |
928 | 949 |
offset += s->cluster_size; |
... | ... | |
934 | 955 |
qcow2_create_refcount_update(s, 0, header_size); |
935 | 956 |
qcow2_create_refcount_update(s, s->l1_table_offset, |
936 | 957 |
l1_size * sizeof(uint64_t)); |
937 |
qcow2_create_refcount_update(s, s->refcount_table_offset, s->cluster_size); |
|
958 |
qcow2_create_refcount_update(s, s->refcount_table_offset, |
|
959 |
reftable_clusters * s->cluster_size); |
|
938 | 960 |
qcow2_create_refcount_update(s, s->refcount_block_offset, |
939 | 961 |
ref_clusters * s->cluster_size); |
940 | 962 |
|
... | ... | |
986 | 1008 |
} |
987 | 1009 |
} |
988 | 1010 |
lseek(fd, s->refcount_table_offset, SEEK_SET); |
989 |
ret = qemu_write_full(fd, s->refcount_table, s->cluster_size); |
|
990 |
if (ret != s->cluster_size) { |
|
1011 |
ret = qemu_write_full(fd, s->refcount_table, |
|
1012 |
reftable_clusters * s->cluster_size); |
|
1013 |
if (ret != reftable_clusters * s->cluster_size) { |
|
991 | 1014 |
ret = -errno; |
992 | 1015 |
goto exit; |
993 | 1016 |
} |
Also available in: Unified diff