Revision 9b036055
b/block/qcow2.c | ||
---|---|---|
795 | 795 |
return qcow2_update_ext_header(bs, backing_file, backing_fmt); |
796 | 796 |
} |
797 | 797 |
|
798 |
#if 0 |
|
799 |
static int get_bits_from_size(size_t size) |
|
800 |
{ |
|
801 |
int res = 0; |
|
802 |
|
|
803 |
if (size == 0) { |
|
804 |
return -1; |
|
805 |
} |
|
806 |
|
|
807 |
while (size != 1) { |
|
808 |
/* Not a power of two */ |
|
809 |
if (size & 1) { |
|
810 |
return -1; |
|
811 |
} |
|
812 |
|
|
813 |
size >>= 1; |
|
814 |
res++; |
|
815 |
} |
|
816 |
|
|
817 |
return res; |
|
818 |
} |
|
819 |
#endif |
|
820 |
|
|
821 |
|
|
822 | 798 |
static int preallocate(BlockDriverState *bs) |
823 | 799 |
{ |
824 | 800 |
uint64_t nb_sectors; |
... | ... | |
872 | 848 |
return 0; |
873 | 849 |
} |
874 | 850 |
|
875 |
#if 0 |
|
876 |
static int qcow_create2(const char *filename, int64_t total_size, |
|
877 |
const char *backing_file, const char *backing_format, |
|
878 |
int flags, size_t cluster_size, int prealloc) |
|
879 |
{ |
|
880 |
|
|
881 |
int fd, header_size, backing_filename_len, l1_size, i, shift, l2_bits; |
|
882 |
int ref_clusters, reftable_clusters, backing_format_len = 0; |
|
883 |
int rounded_ext_bf_len = 0; |
|
884 |
QCowHeader header; |
|
885 |
uint64_t tmp, offset; |
|
886 |
uint64_t old_ref_clusters; |
|
887 |
QCowCreateState s1, *s = &s1; |
|
888 |
QCowExtension ext_bf = {0, 0}; |
|
889 |
int ret; |
|
890 |
|
|
891 |
memset(s, 0, sizeof(*s)); |
|
892 |
|
|
893 |
fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644); |
|
894 |
if (fd < 0) |
|
895 |
return -errno; |
|
896 |
memset(&header, 0, sizeof(header)); |
|
897 |
header.magic = cpu_to_be32(QCOW_MAGIC); |
|
898 |
header.version = cpu_to_be32(QCOW_VERSION); |
|
899 |
header.size = cpu_to_be64(total_size * 512); |
|
900 |
header_size = sizeof(header); |
|
901 |
backing_filename_len = 0; |
|
902 |
if (backing_file) { |
|
903 |
if (backing_format) { |
|
904 |
ext_bf.magic = QCOW_EXT_MAGIC_BACKING_FORMAT; |
|
905 |
backing_format_len = strlen(backing_format); |
|
906 |
ext_bf.len = backing_format_len; |
|
907 |
rounded_ext_bf_len = (sizeof(ext_bf) + ext_bf.len + 7) & ~7; |
|
908 |
header_size += rounded_ext_bf_len; |
|
909 |
} |
|
910 |
header.backing_file_offset = cpu_to_be64(header_size); |
|
911 |
backing_filename_len = strlen(backing_file); |
|
912 |
header.backing_file_size = cpu_to_be32(backing_filename_len); |
|
913 |
header_size += backing_filename_len; |
|
914 |
} |
|
915 |
|
|
916 |
/* Cluster size */ |
|
917 |
s->cluster_bits = get_bits_from_size(cluster_size); |
|
918 |
if (s->cluster_bits < MIN_CLUSTER_BITS || |
|
919 |
s->cluster_bits > MAX_CLUSTER_BITS) |
|
920 |
{ |
|
921 |
fprintf(stderr, "Cluster size must be a power of two between " |
|
922 |
"%d and %dk\n", |
|
923 |
1 << MIN_CLUSTER_BITS, |
|
924 |
1 << (MAX_CLUSTER_BITS - 10)); |
|
925 |
return -EINVAL; |
|
926 |
} |
|
927 |
s->cluster_size = 1 << s->cluster_bits; |
|
928 |
|
|
929 |
header.cluster_bits = cpu_to_be32(s->cluster_bits); |
|
930 |
header_size = (header_size + 7) & ~7; |
|
931 |
if (flags & BLOCK_FLAG_ENCRYPT) { |
|
932 |
header.crypt_method = cpu_to_be32(QCOW_CRYPT_AES); |
|
933 |
} else { |
|
934 |
header.crypt_method = cpu_to_be32(QCOW_CRYPT_NONE); |
|
935 |
} |
|
936 |
l2_bits = s->cluster_bits - 3; |
|
937 |
shift = s->cluster_bits + l2_bits; |
|
938 |
l1_size = (((total_size * 512) + (1LL << shift) - 1) >> shift); |
|
939 |
offset = align_offset(header_size, s->cluster_size); |
|
940 |
s->l1_table_offset = offset; |
|
941 |
header.l1_table_offset = cpu_to_be64(s->l1_table_offset); |
|
942 |
header.l1_size = cpu_to_be32(l1_size); |
|
943 |
offset += align_offset(l1_size * sizeof(uint64_t), s->cluster_size); |
|
944 |
|
|
945 |
/* count how many refcount blocks needed */ |
|
946 |
|
|
947 |
#define NUM_CLUSTERS(bytes) \ |
|
948 |
(((bytes) + (s->cluster_size) - 1) / (s->cluster_size)) |
|
949 |
|
|
950 |
ref_clusters = NUM_CLUSTERS(NUM_CLUSTERS(offset) * sizeof(uint16_t)); |
|
951 |
|
|
952 |
do { |
|
953 |
uint64_t image_clusters; |
|
954 |
old_ref_clusters = ref_clusters; |
|
955 |
|
|
956 |
/* Number of clusters used for the refcount table */ |
|
957 |
reftable_clusters = NUM_CLUSTERS(ref_clusters * sizeof(uint64_t)); |
|
958 |
|
|
959 |
/* Number of clusters that the whole image will have */ |
|
960 |
image_clusters = NUM_CLUSTERS(offset) + ref_clusters |
|
961 |
+ reftable_clusters; |
|
962 |
|
|
963 |
/* Number of refcount blocks needed for the image */ |
|
964 |
ref_clusters = NUM_CLUSTERS(image_clusters * sizeof(uint16_t)); |
|
965 |
|
|
966 |
} while (ref_clusters != old_ref_clusters); |
|
967 |
|
|
968 |
s->refcount_table = qemu_mallocz(reftable_clusters * s->cluster_size); |
|
969 |
|
|
970 |
s->refcount_table_offset = offset; |
|
971 |
header.refcount_table_offset = cpu_to_be64(offset); |
|
972 |
header.refcount_table_clusters = cpu_to_be32(reftable_clusters); |
|
973 |
offset += (reftable_clusters * s->cluster_size); |
|
974 |
s->refcount_block_offset = offset; |
|
975 |
|
|
976 |
for (i=0; i < ref_clusters; i++) { |
|
977 |
s->refcount_table[i] = cpu_to_be64(offset); |
|
978 |
offset += s->cluster_size; |
|
979 |
} |
|
980 |
|
|
981 |
s->refcount_block = qemu_mallocz(ref_clusters * s->cluster_size); |
|
982 |
|
|
983 |
/* update refcounts */ |
|
984 |
qcow2_create_refcount_update(s, 0, header_size); |
|
985 |
qcow2_create_refcount_update(s, s->l1_table_offset, |
|
986 |
l1_size * sizeof(uint64_t)); |
|
987 |
qcow2_create_refcount_update(s, s->refcount_table_offset, |
|
988 |
reftable_clusters * s->cluster_size); |
|
989 |
qcow2_create_refcount_update(s, s->refcount_block_offset, |
|
990 |
ref_clusters * s->cluster_size); |
|
991 |
|
|
992 |
/* write all the data */ |
|
993 |
ret = qemu_write_full(fd, &header, sizeof(header)); |
|
994 |
if (ret != sizeof(header)) { |
|
995 |
ret = -errno; |
|
996 |
goto exit; |
|
997 |
} |
|
998 |
if (backing_file) { |
|
999 |
if (backing_format_len) { |
|
1000 |
char zero[16]; |
|
1001 |
int padding = rounded_ext_bf_len - (ext_bf.len + sizeof(ext_bf)); |
|
1002 |
|
|
1003 |
memset(zero, 0, sizeof(zero)); |
|
1004 |
cpu_to_be32s(&ext_bf.magic); |
|
1005 |
cpu_to_be32s(&ext_bf.len); |
|
1006 |
ret = qemu_write_full(fd, &ext_bf, sizeof(ext_bf)); |
|
1007 |
if (ret != sizeof(ext_bf)) { |
|
1008 |
ret = -errno; |
|
1009 |
goto exit; |
|
1010 |
} |
|
1011 |
ret = qemu_write_full(fd, backing_format, backing_format_len); |
|
1012 |
if (ret != backing_format_len) { |
|
1013 |
ret = -errno; |
|
1014 |
goto exit; |
|
1015 |
} |
|
1016 |
if (padding > 0) { |
|
1017 |
ret = qemu_write_full(fd, zero, padding); |
|
1018 |
if (ret != padding) { |
|
1019 |
ret = -errno; |
|
1020 |
goto exit; |
|
1021 |
} |
|
1022 |
} |
|
1023 |
} |
|
1024 |
ret = qemu_write_full(fd, backing_file, backing_filename_len); |
|
1025 |
if (ret != backing_filename_len) { |
|
1026 |
ret = -errno; |
|
1027 |
goto exit; |
|
1028 |
} |
|
1029 |
} |
|
1030 |
lseek(fd, s->l1_table_offset, SEEK_SET); |
|
1031 |
tmp = 0; |
|
1032 |
for(i = 0;i < l1_size; i++) { |
|
1033 |
ret = qemu_write_full(fd, &tmp, sizeof(tmp)); |
|
1034 |
if (ret != sizeof(tmp)) { |
|
1035 |
ret = -errno; |
|
1036 |
goto exit; |
|
1037 |
} |
|
1038 |
} |
|
1039 |
lseek(fd, s->refcount_table_offset, SEEK_SET); |
|
1040 |
ret = qemu_write_full(fd, s->refcount_table, |
|
1041 |
reftable_clusters * s->cluster_size); |
|
1042 |
if (ret != reftable_clusters * s->cluster_size) { |
|
1043 |
ret = -errno; |
|
1044 |
goto exit; |
|
1045 |
} |
|
1046 |
|
|
1047 |
lseek(fd, s->refcount_block_offset, SEEK_SET); |
|
1048 |
ret = qemu_write_full(fd, s->refcount_block, |
|
1049 |
ref_clusters * s->cluster_size); |
|
1050 |
if (ret != ref_clusters * s->cluster_size) { |
|
1051 |
ret = -errno; |
|
1052 |
goto exit; |
|
1053 |
} |
|
1054 |
|
|
1055 |
ret = 0; |
|
1056 |
exit: |
|
1057 |
qemu_free(s->refcount_table); |
|
1058 |
qemu_free(s->refcount_block); |
|
1059 |
close(fd); |
|
1060 |
|
|
1061 |
/* Preallocate metadata */ |
|
1062 |
if (ret == 0 && prealloc) { |
|
1063 |
BlockDriverState *bs; |
|
1064 |
BlockDriver *drv = bdrv_find_format("qcow2"); |
|
1065 |
bs = bdrv_new(""); |
|
1066 |
bdrv_open(bs, filename, BDRV_O_CACHE_WB | BDRV_O_RDWR, drv); |
|
1067 |
ret = preallocate(bs); |
|
1068 |
bdrv_close(bs); |
|
1069 |
} |
|
1070 |
|
|
1071 |
return ret; |
|
1072 |
} |
|
1073 |
#else |
|
1074 | 851 |
static int qcow_create2(const char *filename, int64_t total_size, |
1075 | 852 |
const char *backing_file, const char *backing_format, |
1076 | 853 |
int flags, size_t cluster_size, int prealloc, |
... | ... | |
1196 | 973 |
bdrv_delete(bs); |
1197 | 974 |
return ret; |
1198 | 975 |
} |
1199 |
#endif |
|
1200 | 976 |
|
1201 | 977 |
static int qcow_create(const char *filename, QEMUOptionParameter *options) |
1202 | 978 |
{ |
Also available in: Unified diff