2 * Block driver for the VMDK format
4 * Copyright (c) 2004 Fabrice Bellard
5 * Copyright (c) 2005 Filip Navara
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26 #include "qemu-common.h"
27 #include "block_int.h"
30 #define VMDK3_MAGIC (('C' << 24) | ('O' << 16) | ('W' << 8) | 'D')
31 #define VMDK4_MAGIC (('K' << 24) | ('D' << 16) | ('M' << 8) | 'V')
36 uint32_t disk_sectors;
38 uint32_t l1dir_offset;
40 uint32_t file_sectors;
43 uint32_t sectors_per_track;
53 int32_t num_gtes_per_gte;
59 } __attribute__((packed)) VMDK4Header;
61 #define L2_CACHE_SIZE 16
63 typedef struct VmdkExtent {
64 BlockDriverState *file;
68 int64_t l1_table_offset;
69 int64_t l1_backup_table_offset;
71 uint32_t *l1_backup_table;
73 uint32_t l1_entry_sectors;
77 uint32_t l2_cache_offsets[L2_CACHE_SIZE];
78 uint32_t l2_cache_counts[L2_CACHE_SIZE];
80 unsigned int cluster_sectors;
83 typedef struct BDRVVmdkState {
86 /* Extent array with num_extents entries, ascend ordered by address */
90 typedef struct VmdkMetaData {
92 unsigned int l1_index;
93 unsigned int l2_index;
94 unsigned int l2_offset;
98 static int vmdk_probe(const uint8_t *buf, int buf_size, const char *filename)
104 magic = be32_to_cpu(*(uint32_t *)buf);
105 if (magic == VMDK3_MAGIC ||
106 magic == VMDK4_MAGIC) {
109 const char *p = (const char *)buf;
110 const char *end = p + buf_size;
113 /* skip comment line */
114 while (p < end && *p != '\n') {
121 while (p < end && *p == ' ') {
124 /* skip '\r' if windows line endings used. */
125 if (p < end && *p == '\r') {
128 /* only accept blank lines before 'version=' line */
129 if (p == end || *p != '\n') {
135 if (end - p >= strlen("version=X\n")) {
136 if (strncmp("version=1\n", p, strlen("version=1\n")) == 0 ||
137 strncmp("version=2\n", p, strlen("version=2\n")) == 0) {
141 if (end - p >= strlen("version=X\r\n")) {
142 if (strncmp("version=1\r\n", p, strlen("version=1\r\n")) == 0 ||
143 strncmp("version=2\r\n", p, strlen("version=2\r\n")) == 0) {
155 #define SECTOR_SIZE 512
156 #define DESC_SIZE 20*SECTOR_SIZE // 20 sectors of 512 bytes each
157 #define HEADER_SIZE 512 // first sector of 512 bytes
159 static void vmdk_free_extents(BlockDriverState *bs)
162 BDRVVmdkState *s = bs->opaque;
164 for (i = 0; i < s->num_extents; i++) {
165 qemu_free(s->extents[i].l1_table);
166 qemu_free(s->extents[i].l2_cache);
167 qemu_free(s->extents[i].l1_backup_table);
169 qemu_free(s->extents);
172 static uint32_t vmdk_read_cid(BlockDriverState *bs, int parent)
174 char desc[DESC_SIZE];
176 const char *p_name, *cid_str;
179 /* the descriptor offset = 0x200 */
180 if (bdrv_pread(bs->file, 0x200, desc, DESC_SIZE) != DESC_SIZE)
184 cid_str = "parentCID";
185 cid_str_size = sizeof("parentCID");
188 cid_str_size = sizeof("CID");
191 if ((p_name = strstr(desc,cid_str)) != NULL) {
192 p_name += cid_str_size;
193 sscanf(p_name,"%x",&cid);
199 static int vmdk_write_cid(BlockDriverState *bs, uint32_t cid)
201 char desc[DESC_SIZE], tmp_desc[DESC_SIZE];
202 char *p_name, *tmp_str;
204 /* the descriptor offset = 0x200 */
205 if (bdrv_pread(bs->file, 0x200, desc, DESC_SIZE) != DESC_SIZE)
208 tmp_str = strstr(desc,"parentCID");
209 pstrcpy(tmp_desc, sizeof(tmp_desc), tmp_str);
210 if ((p_name = strstr(desc,"CID")) != NULL) {
211 p_name += sizeof("CID");
212 snprintf(p_name, sizeof(desc) - (p_name - desc), "%x\n", cid);
213 pstrcat(desc, sizeof(desc), tmp_desc);
216 if (bdrv_pwrite_sync(bs->file, 0x200, desc, DESC_SIZE) < 0)
221 static int vmdk_is_cid_valid(BlockDriverState *bs)
224 BDRVVmdkState *s = bs->opaque;
225 BlockDriverState *p_bs = bs->backing_hd;
229 cur_pcid = vmdk_read_cid(p_bs,0);
230 if (s->parent_cid != cur_pcid)
239 static int vmdk_snapshot_create(const char *filename, const char *backing_file)
244 char *p_name, *gd_buf, *rgd_buf;
245 const char *real_filename, *temp_str;
247 uint32_t gde_entries, gd_size;
248 int64_t gd_offset, rgd_offset, capacity, gt_size;
249 char p_desc[DESC_SIZE], s_desc[DESC_SIZE], hdr[HEADER_SIZE];
250 static const char desc_template[] =
251 "# Disk DescriptorFile\n"
255 "createType=\"monolithicSparse\"\n"
256 "parentFileNameHint=\"%s\"\n"
258 "# Extent description\n"
259 "RW %u SPARSE \"%s\"\n"
261 "# The Disk Data Base \n"
265 snp_fd = open(filename, O_RDWR | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE, 0644);
268 p_fd = open(backing_file, O_RDONLY | O_BINARY | O_LARGEFILE);
274 /* read the header */
275 if (lseek(p_fd, 0x0, SEEK_SET) == -1) {
279 if (read(p_fd, hdr, HEADER_SIZE) != HEADER_SIZE) {
284 /* write the header */
285 if (lseek(snp_fd, 0x0, SEEK_SET) == -1) {
289 if (write(snp_fd, hdr, HEADER_SIZE) == -1) {
294 memset(&header, 0, sizeof(header));
295 memcpy(&header,&hdr[4], sizeof(header)); // skip the VMDK4_MAGIC
297 if (ftruncate(snp_fd, header.grain_offset << 9)) {
301 /* the descriptor offset = 0x200 */
302 if (lseek(p_fd, 0x200, SEEK_SET) == -1) {
306 if (read(p_fd, p_desc, DESC_SIZE) != DESC_SIZE) {
311 if ((p_name = strstr(p_desc,"CID")) != NULL) {
312 p_name += sizeof("CID");
313 sscanf(p_name,"%x",&p_cid);
316 real_filename = filename;
317 if ((temp_str = strrchr(real_filename, '\\')) != NULL)
318 real_filename = temp_str + 1;
319 if ((temp_str = strrchr(real_filename, '/')) != NULL)
320 real_filename = temp_str + 1;
321 if ((temp_str = strrchr(real_filename, ':')) != NULL)
322 real_filename = temp_str + 1;
324 snprintf(s_desc, sizeof(s_desc), desc_template, p_cid, p_cid, backing_file,
325 (uint32_t)header.capacity, real_filename);
327 /* write the descriptor */
328 if (lseek(snp_fd, 0x200, SEEK_SET) == -1) {
332 if (write(snp_fd, s_desc, strlen(s_desc)) == -1) {
337 gd_offset = header.gd_offset * SECTOR_SIZE; // offset of GD table
338 rgd_offset = header.rgd_offset * SECTOR_SIZE; // offset of RGD table
339 capacity = header.capacity * SECTOR_SIZE; // Extent size
341 * Each GDE span 32M disk, means:
342 * 512 GTE per GT, each GTE points to grain
344 gt_size = (int64_t)header.num_gtes_per_gte * header.granularity * SECTOR_SIZE;
349 gde_entries = (uint32_t)(capacity / gt_size); // number of gde/rgde
350 gd_size = gde_entries * sizeof(uint32_t);
353 rgd_buf = qemu_malloc(gd_size);
354 if (lseek(p_fd, rgd_offset, SEEK_SET) == -1) {
358 if (read(p_fd, rgd_buf, gd_size) != gd_size) {
362 if (lseek(snp_fd, rgd_offset, SEEK_SET) == -1) {
366 if (write(snp_fd, rgd_buf, gd_size) == -1) {
372 gd_buf = qemu_malloc(gd_size);
373 if (lseek(p_fd, gd_offset, SEEK_SET) == -1) {
377 if (read(p_fd, gd_buf, gd_size) != gd_size) {
381 if (lseek(snp_fd, gd_offset, SEEK_SET) == -1) {
385 if (write(snp_fd, gd_buf, gd_size) == -1) {
401 static int vmdk_parent_open(BlockDriverState *bs)
404 char desc[DESC_SIZE];
406 /* the descriptor offset = 0x200 */
407 if (bdrv_pread(bs->file, 0x200, desc, DESC_SIZE) != DESC_SIZE)
410 if ((p_name = strstr(desc,"parentFileNameHint")) != NULL) {
413 p_name += sizeof("parentFileNameHint") + 1;
414 if ((end_name = strchr(p_name,'\"')) == NULL)
416 if ((end_name - p_name) > sizeof (bs->backing_file) - 1)
419 pstrcpy(bs->backing_file, end_name - p_name + 1, p_name);
425 /* Create and append extent to the extent array. Return the added VmdkExtent
426 * address. return NULL if allocation failed. */
427 static VmdkExtent *vmdk_add_extent(BlockDriverState *bs,
428 BlockDriverState *file, bool flat, int64_t sectors,
429 int64_t l1_offset, int64_t l1_backup_offset,
431 int l2_size, unsigned int cluster_sectors)
434 BDRVVmdkState *s = bs->opaque;
436 s->extents = qemu_realloc(s->extents,
437 (s->num_extents + 1) * sizeof(VmdkExtent));
438 extent = &s->extents[s->num_extents];
441 memset(extent, 0, sizeof(VmdkExtent));
444 extent->sectors = sectors;
445 extent->l1_table_offset = l1_offset;
446 extent->l1_backup_table_offset = l1_backup_offset;
447 extent->l1_size = l1_size;
448 extent->l1_entry_sectors = l2_size * cluster_sectors;
449 extent->l2_size = l2_size;
450 extent->cluster_sectors = cluster_sectors;
452 if (s->num_extents > 1) {
453 extent->end_sector = (*(extent - 1)).end_sector + extent->sectors;
455 extent->end_sector = extent->sectors;
457 bs->total_sectors = extent->end_sector;
461 static int vmdk_init_tables(BlockDriverState *bs, VmdkExtent *extent)
466 /* read the L1 table */
467 l1_size = extent->l1_size * sizeof(uint32_t);
468 extent->l1_table = qemu_malloc(l1_size);
469 ret = bdrv_pread(extent->file,
470 extent->l1_table_offset,
476 for (i = 0; i < extent->l1_size; i++) {
477 le32_to_cpus(&extent->l1_table[i]);
480 if (extent->l1_backup_table_offset) {
481 extent->l1_backup_table = qemu_malloc(l1_size);
482 ret = bdrv_pread(extent->file,
483 extent->l1_backup_table_offset,
484 extent->l1_backup_table,
489 for (i = 0; i < extent->l1_size; i++) {
490 le32_to_cpus(&extent->l1_backup_table[i]);
495 qemu_malloc(extent->l2_size * L2_CACHE_SIZE * sizeof(uint32_t));
498 qemu_free(extent->l1_backup_table);
500 qemu_free(extent->l1_table);
504 static int vmdk_open_vmdk3(BlockDriverState *bs, int flags)
511 ret = bdrv_pread(bs->file, sizeof(magic), &header, sizeof(header));
515 extent = vmdk_add_extent(bs,
517 le32_to_cpu(header.disk_sectors),
518 le32_to_cpu(header.l1dir_offset) << 9,
520 le32_to_cpu(header.granularity));
521 ret = vmdk_init_tables(bs, extent);
523 /* vmdk_init_tables cleans up on fail, so only free allocation of
524 * vmdk_add_extent here. */
529 vmdk_free_extents(bs);
533 static int vmdk_open_vmdk4(BlockDriverState *bs, int flags)
537 uint32_t l1_size, l1_entry_sectors;
539 BDRVVmdkState *s = bs->opaque;
542 ret = bdrv_pread(bs->file, sizeof(magic), &header, sizeof(header));
546 l1_entry_sectors = le32_to_cpu(header.num_gtes_per_gte)
547 * le64_to_cpu(header.granularity);
548 l1_size = (le64_to_cpu(header.capacity) + l1_entry_sectors - 1)
550 extent = vmdk_add_extent(bs, bs->file, false,
551 le64_to_cpu(header.capacity),
552 le64_to_cpu(header.gd_offset) << 9,
553 le64_to_cpu(header.rgd_offset) << 9,
555 le32_to_cpu(header.num_gtes_per_gte),
556 le64_to_cpu(header.granularity));
557 if (extent->l1_entry_sectors <= 0) {
561 /* try to open parent images, if exist */
562 ret = vmdk_parent_open(bs);
566 s->parent_cid = vmdk_read_cid(bs, 1);
567 ret = vmdk_init_tables(bs, extent);
573 vmdk_free_extents(bs);
577 static int vmdk_open(BlockDriverState *bs, int flags)
581 if (bdrv_pread(bs->file, 0, &magic, sizeof(magic)) != sizeof(magic)) {
585 magic = be32_to_cpu(magic);
586 if (magic == VMDK3_MAGIC) {
587 return vmdk_open_vmdk3(bs, flags);
588 } else if (magic == VMDK4_MAGIC) {
589 return vmdk_open_vmdk4(bs, flags);
595 static int get_whole_cluster(BlockDriverState *bs,
597 uint64_t cluster_offset,
601 /* 128 sectors * 512 bytes each = grain size 64KB */
602 uint8_t whole_grain[extent->cluster_sectors * 512];
604 /* we will be here if it's first write on non-exist grain(cluster).
605 * try to read from parent image, if exist */
606 if (bs->backing_hd) {
609 if (!vmdk_is_cid_valid(bs))
612 /* floor offset to cluster */
613 offset -= offset % (extent->cluster_sectors * 512);
614 ret = bdrv_read(bs->backing_hd, offset >> 9, whole_grain,
615 extent->cluster_sectors);
620 /* Write grain only into the active image */
621 ret = bdrv_write(extent->file, cluster_offset, whole_grain,
622 extent->cluster_sectors);
630 static int vmdk_L2update(VmdkExtent *extent, VmdkMetaData *m_data)
632 /* update L2 table */
633 if (bdrv_pwrite_sync(
635 ((int64_t)m_data->l2_offset * 512)
636 + (m_data->l2_index * sizeof(m_data->offset)),
638 sizeof(m_data->offset)
642 /* update backup L2 table */
643 if (extent->l1_backup_table_offset != 0) {
644 m_data->l2_offset = extent->l1_backup_table[m_data->l1_index];
645 if (bdrv_pwrite_sync(
647 ((int64_t)m_data->l2_offset * 512)
648 + (m_data->l2_index * sizeof(m_data->offset)),
649 &(m_data->offset), sizeof(m_data->offset)
658 static uint64_t get_cluster_offset(BlockDriverState *bs,
660 VmdkMetaData *m_data,
661 uint64_t offset, int allocate)
663 unsigned int l1_index, l2_offset, l2_index;
665 uint32_t min_count, *l2_table, tmp = 0;
666 uint64_t cluster_offset;
671 l1_index = (offset >> 9) / extent->l1_entry_sectors;
672 if (l1_index >= extent->l1_size) {
675 l2_offset = extent->l1_table[l1_index];
679 for (i = 0; i < L2_CACHE_SIZE; i++) {
680 if (l2_offset == extent->l2_cache_offsets[i]) {
681 /* increment the hit count */
682 if (++extent->l2_cache_counts[i] == 0xffffffff) {
683 for (j = 0; j < L2_CACHE_SIZE; j++) {
684 extent->l2_cache_counts[j] >>= 1;
687 l2_table = extent->l2_cache + (i * extent->l2_size);
691 /* not found: load a new entry in the least used one */
693 min_count = 0xffffffff;
694 for (i = 0; i < L2_CACHE_SIZE; i++) {
695 if (extent->l2_cache_counts[i] < min_count) {
696 min_count = extent->l2_cache_counts[i];
700 l2_table = extent->l2_cache + (min_index * extent->l2_size);
703 (int64_t)l2_offset * 512,
705 extent->l2_size * sizeof(uint32_t)
706 ) != extent->l2_size * sizeof(uint32_t)) {
710 extent->l2_cache_offsets[min_index] = l2_offset;
711 extent->l2_cache_counts[min_index] = 1;
713 l2_index = ((offset >> 9) / extent->cluster_sectors) % extent->l2_size;
714 cluster_offset = le32_to_cpu(l2_table[l2_index]);
716 if (!cluster_offset) {
720 // Avoid the L2 tables update for the images that have snapshots.
721 cluster_offset = bdrv_getlength(extent->file);
724 cluster_offset + (extent->cluster_sectors << 9)
727 cluster_offset >>= 9;
728 tmp = cpu_to_le32(cluster_offset);
729 l2_table[l2_index] = tmp;
731 /* First of all we write grain itself, to avoid race condition
732 * that may to corrupt the image.
733 * This problem may occur because of insufficient space on host disk
734 * or inappropriate VM shutdown.
736 if (get_whole_cluster(
737 bs, extent, cluster_offset, offset, allocate) == -1)
741 m_data->offset = tmp;
742 m_data->l1_index = l1_index;
743 m_data->l2_index = l2_index;
744 m_data->l2_offset = l2_offset;
748 cluster_offset <<= 9;
749 return cluster_offset;
752 static VmdkExtent *find_extent(BDRVVmdkState *s,
753 int64_t sector_num, VmdkExtent *start_hint)
755 VmdkExtent *extent = start_hint;
758 extent = &s->extents[0];
760 while (extent < &s->extents[s->num_extents]) {
761 if (sector_num < extent->end_sector) {
769 static int vmdk_is_allocated(BlockDriverState *bs, int64_t sector_num,
770 int nb_sectors, int *pnum)
772 BDRVVmdkState *s = bs->opaque;
774 int64_t index_in_cluster, n, ret;
778 extent = find_extent(s, sector_num, NULL);
783 n = extent->end_sector - sector_num;
786 offset = get_cluster_offset(bs, extent, NULL, sector_num * 512, 0);
787 index_in_cluster = sector_num % extent->cluster_sectors;
788 n = extent->cluster_sectors - index_in_cluster;
789 ret = offset ? 1 : 0;
797 static int vmdk_read(BlockDriverState *bs, int64_t sector_num,
798 uint8_t *buf, int nb_sectors)
800 BDRVVmdkState *s = bs->opaque;
802 uint64_t n, index_in_cluster;
803 VmdkExtent *extent = NULL;
804 uint64_t cluster_offset;
806 while (nb_sectors > 0) {
807 extent = find_extent(s, sector_num, extent);
811 cluster_offset = get_cluster_offset(
812 bs, extent, NULL, sector_num << 9, 0);
813 index_in_cluster = sector_num % extent->cluster_sectors;
814 n = extent->cluster_sectors - index_in_cluster;
817 if (!cluster_offset) {
818 // try to read from parent image, if exist
819 if (bs->backing_hd) {
820 if (!vmdk_is_cid_valid(bs))
822 ret = bdrv_read(bs->backing_hd, sector_num, buf, n);
826 memset(buf, 0, 512 * n);
829 if(bdrv_pread(bs->file, cluster_offset + index_in_cluster * 512, buf, n * 512) != n * 512)
839 static int vmdk_write(BlockDriverState *bs, int64_t sector_num,
840 const uint8_t *buf, int nb_sectors)
842 BDRVVmdkState *s = bs->opaque;
843 VmdkExtent *extent = NULL;
845 int64_t index_in_cluster;
846 uint64_t cluster_offset;
847 static int cid_update = 0;
850 if (sector_num > bs->total_sectors) {
852 "(VMDK) Wrong offset: sector_num=0x%" PRIx64
853 " total_sectors=0x%" PRIx64 "\n",
854 sector_num, bs->total_sectors);
858 while (nb_sectors > 0) {
859 extent = find_extent(s, sector_num, extent);
863 cluster_offset = get_cluster_offset(
868 if (!cluster_offset) {
871 index_in_cluster = sector_num % extent->cluster_sectors;
872 n = extent->cluster_sectors - index_in_cluster;
873 if (n > nb_sectors) {
877 if (bdrv_pwrite(bs->file,
878 cluster_offset + index_in_cluster * 512,
884 /* update L2 tables */
885 if (vmdk_L2update(extent, &m_data) == -1) {
893 // update CID on the first write every time the virtual disk is opened
895 vmdk_write_cid(bs, time(NULL));
902 static int vmdk_create(const char *filename, QEMUOptionParameter *options)
906 uint32_t tmp, magic, grains, gd_size, gt_size, gt_count;
907 static const char desc_template[] =
908 "# Disk DescriptorFile\n"
911 "parentCID=ffffffff\n"
912 "createType=\"monolithicSparse\"\n"
914 "# Extent description\n"
915 "RW %" PRId64 " SPARSE \"%s\"\n"
917 "# The Disk Data Base \n"
920 "ddb.virtualHWVersion = \"%d\"\n"
921 "ddb.geometry.cylinders = \"%" PRId64 "\"\n"
922 "ddb.geometry.heads = \"16\"\n"
923 "ddb.geometry.sectors = \"63\"\n"
924 "ddb.adapterType = \"ide\"\n";
926 const char *real_filename, *temp_str;
927 int64_t total_size = 0;
928 const char *backing_file = NULL;
933 while (options && options->name) {
934 if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
935 total_size = options->value.n / 512;
936 } else if (!strcmp(options->name, BLOCK_OPT_BACKING_FILE)) {
937 backing_file = options->value.s;
938 } else if (!strcmp(options->name, BLOCK_OPT_COMPAT6)) {
939 flags |= options->value.n ? BLOCK_FLAG_COMPAT6: 0;
944 /* XXX: add support for backing file */
946 return vmdk_snapshot_create(filename, backing_file);
949 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE,
953 magic = cpu_to_be32(VMDK4_MAGIC);
954 memset(&header, 0, sizeof(header));
956 header.flags = 3; /* ?? */
957 header.capacity = total_size;
958 header.granularity = 128;
959 header.num_gtes_per_gte = 512;
961 grains = (total_size + header.granularity - 1) / header.granularity;
962 gt_size = ((header.num_gtes_per_gte * sizeof(uint32_t)) + 511) >> 9;
963 gt_count = (grains + header.num_gtes_per_gte - 1) / header.num_gtes_per_gte;
964 gd_size = (gt_count * sizeof(uint32_t) + 511) >> 9;
966 header.desc_offset = 1;
967 header.desc_size = 20;
968 header.rgd_offset = header.desc_offset + header.desc_size;
969 header.gd_offset = header.rgd_offset + gd_size + (gt_size * gt_count);
970 header.grain_offset =
971 ((header.gd_offset + gd_size + (gt_size * gt_count) +
972 header.granularity - 1) / header.granularity) *
975 /* swap endianness for all header fields */
976 header.version = cpu_to_le32(header.version);
977 header.flags = cpu_to_le32(header.flags);
978 header.capacity = cpu_to_le64(header.capacity);
979 header.granularity = cpu_to_le64(header.granularity);
980 header.num_gtes_per_gte = cpu_to_le32(header.num_gtes_per_gte);
981 header.desc_offset = cpu_to_le64(header.desc_offset);
982 header.desc_size = cpu_to_le64(header.desc_size);
983 header.rgd_offset = cpu_to_le64(header.rgd_offset);
984 header.gd_offset = cpu_to_le64(header.gd_offset);
985 header.grain_offset = cpu_to_le64(header.grain_offset);
987 header.check_bytes[0] = 0xa;
988 header.check_bytes[1] = 0x20;
989 header.check_bytes[2] = 0xd;
990 header.check_bytes[3] = 0xa;
992 /* write all the data */
993 ret = qemu_write_full(fd, &magic, sizeof(magic));
994 if (ret != sizeof(magic)) {
998 ret = qemu_write_full(fd, &header, sizeof(header));
999 if (ret != sizeof(header)) {
1004 ret = ftruncate(fd, le64_to_cpu(header.grain_offset) << 9);
1010 /* write grain directory */
1011 lseek(fd, le64_to_cpu(header.rgd_offset) << 9, SEEK_SET);
1012 for (i = 0, tmp = le64_to_cpu(header.rgd_offset) + gd_size;
1013 i < gt_count; i++, tmp += gt_size) {
1014 ret = qemu_write_full(fd, &tmp, sizeof(tmp));
1015 if (ret != sizeof(tmp)) {
1021 /* write backup grain directory */
1022 lseek(fd, le64_to_cpu(header.gd_offset) << 9, SEEK_SET);
1023 for (i = 0, tmp = le64_to_cpu(header.gd_offset) + gd_size;
1024 i < gt_count; i++, tmp += gt_size) {
1025 ret = qemu_write_full(fd, &tmp, sizeof(tmp));
1026 if (ret != sizeof(tmp)) {
1032 /* compose the descriptor */
1033 real_filename = filename;
1034 if ((temp_str = strrchr(real_filename, '\\')) != NULL)
1035 real_filename = temp_str + 1;
1036 if ((temp_str = strrchr(real_filename, '/')) != NULL)
1037 real_filename = temp_str + 1;
1038 if ((temp_str = strrchr(real_filename, ':')) != NULL)
1039 real_filename = temp_str + 1;
1040 snprintf(desc, sizeof(desc), desc_template, (unsigned int)time(NULL),
1041 total_size, real_filename,
1042 (flags & BLOCK_FLAG_COMPAT6 ? 6 : 4),
1043 total_size / (int64_t)(63 * 16));
1045 /* write the descriptor */
1046 lseek(fd, le64_to_cpu(header.desc_offset) << 9, SEEK_SET);
1047 ret = qemu_write_full(fd, desc, strlen(desc));
1048 if (ret != strlen(desc)) {
1059 static void vmdk_close(BlockDriverState *bs)
1061 vmdk_free_extents(bs);
1064 static int vmdk_flush(BlockDriverState *bs)
1066 return bdrv_flush(bs->file);
1070 static QEMUOptionParameter vmdk_create_options[] = {
1072 .name = BLOCK_OPT_SIZE,
1074 .help = "Virtual disk size"
1077 .name = BLOCK_OPT_BACKING_FILE,
1079 .help = "File name of a base image"
1082 .name = BLOCK_OPT_COMPAT6,
1084 .help = "VMDK version 6 image"
1089 static BlockDriver bdrv_vmdk = {
1090 .format_name = "vmdk",
1091 .instance_size = sizeof(BDRVVmdkState),
1092 .bdrv_probe = vmdk_probe,
1093 .bdrv_open = vmdk_open,
1094 .bdrv_read = vmdk_read,
1095 .bdrv_write = vmdk_write,
1096 .bdrv_close = vmdk_close,
1097 .bdrv_create = vmdk_create,
1098 .bdrv_flush = vmdk_flush,
1099 .bdrv_is_allocated = vmdk_is_allocated,
1101 .create_options = vmdk_create_options,
1104 static void bdrv_vmdk_init(void)
1106 bdrv_register(&bdrv_vmdk);
1109 block_init(bdrv_vmdk_init);