diff options
Diffstat (limited to 'tools/qemu/patches')
12 files changed, 0 insertions, 2340 deletions
diff --git a/tools/qemu/patches/0001-vmdk-fix-endianness-bugs.patch b/tools/qemu/patches/0001-vmdk-fix-endianness-bugs.patch deleted file mode 100644 index 7e1abb49bf..0000000000 --- a/tools/qemu/patches/0001-vmdk-fix-endianness-bugs.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 6afca0fc5430db0300fe53f2b9cd7d071a3925bb Mon Sep 17 00:00:00 2001 -From: Alexander Graf <agraf@suse.de> -Date: Wed, 25 May 2011 00:46:55 +0200 -Subject: [PATCH 01/12] vmdk: fix endianness bugs - -The vmdk code is sloppy when handling the header descriptor during -creation of an image. Fix all header accesses in the create path to -either store native endianness or convert it when appropriate. - -Reported-by: Yury Tsarev <ytsarev@novell.com> -Signed-off-by: Alexander Graf <agraf@suse.de> -Signed-off-by: Kevin Wolf <kwolf@redhat.com> ---- - block/vmdk.c | 22 ++++++++++++++-------- - 1 file changed, 14 insertions(+), 8 deletions(-) - ---- a/block/vmdk.c -+++ b/block/vmdk.c -@@ -716,11 +716,11 @@ static int vmdk_create(const char *filen - return -errno; - magic = cpu_to_be32(VMDK4_MAGIC); - memset(&header, 0, sizeof(header)); -- header.version = cpu_to_le32(1); -- header.flags = cpu_to_le32(3); /* ?? */ -- header.capacity = cpu_to_le64(total_size); -- header.granularity = cpu_to_le64(128); -- header.num_gtes_per_gte = cpu_to_le32(512); -+ header.version = 1; -+ header.flags = 3; /* ?? */ -+ header.capacity = total_size; -+ header.granularity = 128; -+ header.num_gtes_per_gte = 512; - - grains = (total_size + header.granularity - 1) / header.granularity; - gt_size = ((header.num_gtes_per_gte * sizeof(uint32_t)) + 511) >> 9; -@@ -736,6 +736,12 @@ static int vmdk_create(const char *filen - header.granularity - 1) / header.granularity) * - header.granularity; - -+ /* swap endianness for all header fields */ -+ header.version = cpu_to_le32(header.version); -+ header.flags = cpu_to_le32(header.flags); -+ header.capacity = cpu_to_le64(header.capacity); -+ header.granularity = cpu_to_le64(header.granularity); -+ header.num_gtes_per_gte = cpu_to_le32(header.num_gtes_per_gte); - header.desc_offset = cpu_to_le64(header.desc_offset); - header.desc_size = cpu_to_le64(header.desc_size); - header.rgd_offset = cpu_to_le64(header.rgd_offset); -@@ -759,7 +765,7 @@ static int vmdk_create(const char *filen - goto exit; - } - -- ret = ftruncate(fd, header.grain_offset << 9); -+ ret = ftruncate(fd, le64_to_cpu(header.grain_offset) << 9); - if (ret < 0) { - ret = -errno; - goto exit; -@@ -767,7 +773,7 @@ static int vmdk_create(const char *filen - - /* write grain directory */ - lseek(fd, le64_to_cpu(header.rgd_offset) << 9, SEEK_SET); -- for (i = 0, tmp = header.rgd_offset + gd_size; -+ for (i = 0, tmp = le64_to_cpu(header.rgd_offset) + gd_size; - i < gt_count; i++, tmp += gt_size) { - ret = qemu_write_full(fd, &tmp, sizeof(tmp)); - if (ret != sizeof(tmp)) { -@@ -778,7 +784,7 @@ static int vmdk_create(const char *filen - - /* write backup grain directory */ - lseek(fd, le64_to_cpu(header.gd_offset) << 9, SEEK_SET); -- for (i = 0, tmp = header.gd_offset + gd_size; -+ for (i = 0, tmp = le64_to_cpu(header.gd_offset) + gd_size; - i < gt_count; i++, tmp += gt_size) { - ret = qemu_write_full(fd, &tmp, sizeof(tmp)); - if (ret != sizeof(tmp)) { diff --git a/tools/qemu/patches/0002-VMDK-introduce-VmdkExtent.patch b/tools/qemu/patches/0002-VMDK-introduce-VmdkExtent.patch deleted file mode 100644 index 054b143245..0000000000 --- a/tools/qemu/patches/0002-VMDK-introduce-VmdkExtent.patch +++ /dev/null @@ -1,557 +0,0 @@ -From fcd9c52d160376184cbd25e04586aa6eef6abd61 Mon Sep 17 00:00:00 2001 -From: Fam Zheng <famcool@gmail.com> -Date: Tue, 12 Jul 2011 19:56:28 +0800 -Subject: [PATCH 02/12] VMDK: introduce VmdkExtent - -Introduced VmdkExtent array into BDRVVmdkState, enable holding multiple -image extents for multiple file image support. - -Signed-off-by: Fam Zheng <famcool@gmail.com> -Reviewed-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com> -Signed-off-by: Kevin Wolf <kwolf@redhat.com> ---- - block/vmdk.c | 348 +++++++++++++++++++++++++++++++++++++++++------------------ - 1 file changed, 246 insertions(+), 102 deletions(-) - ---- a/block/vmdk.c -+++ b/block/vmdk.c -@@ -60,7 +60,11 @@ typedef struct { - - #define L2_CACHE_SIZE 16 - --typedef struct BDRVVmdkState { -+typedef struct VmdkExtent { -+ BlockDriverState *file; -+ bool flat; -+ int64_t sectors; -+ int64_t end_sector; - int64_t l1_table_offset; - int64_t l1_backup_table_offset; - uint32_t *l1_table; -@@ -74,7 +78,13 @@ typedef struct BDRVVmdkState { - uint32_t l2_cache_counts[L2_CACHE_SIZE]; - - unsigned int cluster_sectors; -+} VmdkExtent; -+ -+typedef struct BDRVVmdkState { - uint32_t parent_cid; -+ int num_extents; -+ /* Extent array with num_extents entries, ascend ordered by address */ -+ VmdkExtent *extents; - } BDRVVmdkState; - - typedef struct VmdkMetaData { -@@ -105,6 +115,19 @@ static int vmdk_probe(const uint8_t *buf - #define DESC_SIZE 20*SECTOR_SIZE // 20 sectors of 512 bytes each - #define HEADER_SIZE 512 // first sector of 512 bytes - -+static void vmdk_free_extents(BlockDriverState *bs) -+{ -+ int i; -+ BDRVVmdkState *s = bs->opaque; -+ -+ for (i = 0; i < s->num_extents; i++) { -+ qemu_free(s->extents[i].l1_table); -+ qemu_free(s->extents[i].l2_cache); -+ qemu_free(s->extents[i].l1_backup_table); -+ } -+ qemu_free(s->extents); -+} -+ - static uint32_t vmdk_read_cid(BlockDriverState *bs, int parent) - { - char desc[DESC_SIZE]; -@@ -358,11 +381,50 @@ static int vmdk_parent_open(BlockDriverS - return 0; - } - -+/* Create and append extent to the extent array. Return the added VmdkExtent -+ * address. return NULL if allocation failed. */ -+static VmdkExtent *vmdk_add_extent(BlockDriverState *bs, -+ BlockDriverState *file, bool flat, int64_t sectors, -+ int64_t l1_offset, int64_t l1_backup_offset, -+ uint32_t l1_size, -+ int l2_size, unsigned int cluster_sectors) -+{ -+ VmdkExtent *extent; -+ BDRVVmdkState *s = bs->opaque; -+ -+ s->extents = qemu_realloc(s->extents, -+ (s->num_extents + 1) * sizeof(VmdkExtent)); -+ extent = &s->extents[s->num_extents]; -+ s->num_extents++; -+ -+ memset(extent, 0, sizeof(VmdkExtent)); -+ extent->file = file; -+ extent->flat = flat; -+ extent->sectors = sectors; -+ extent->l1_table_offset = l1_offset; -+ extent->l1_backup_table_offset = l1_backup_offset; -+ extent->l1_size = l1_size; -+ extent->l1_entry_sectors = l2_size * cluster_sectors; -+ extent->l2_size = l2_size; -+ extent->cluster_sectors = cluster_sectors; -+ -+ if (s->num_extents > 1) { -+ extent->end_sector = (*(extent - 1)).end_sector + extent->sectors; -+ } else { -+ extent->end_sector = extent->sectors; -+ } -+ bs->total_sectors = extent->end_sector; -+ return extent; -+} -+ -+ - static int vmdk_open(BlockDriverState *bs, int flags) - { - BDRVVmdkState *s = bs->opaque; - uint32_t magic; -- int l1_size, i; -+ int i; -+ uint32_t l1_size, l1_entry_sectors; -+ VmdkExtent *extent = NULL; - - if (bdrv_pread(bs->file, 0, &magic, sizeof(magic)) != sizeof(magic)) - goto fail; -@@ -370,32 +432,34 @@ static int vmdk_open(BlockDriverState *b - magic = be32_to_cpu(magic); - if (magic == VMDK3_MAGIC) { - VMDK3Header header; -- -- if (bdrv_pread(bs->file, sizeof(magic), &header, sizeof(header)) != sizeof(header)) -+ if (bdrv_pread(bs->file, sizeof(magic), &header, sizeof(header)) -+ != sizeof(header)) { - goto fail; -- s->cluster_sectors = le32_to_cpu(header.granularity); -- s->l2_size = 1 << 9; -- s->l1_size = 1 << 6; -- bs->total_sectors = le32_to_cpu(header.disk_sectors); -- s->l1_table_offset = le32_to_cpu(header.l1dir_offset) << 9; -- s->l1_backup_table_offset = 0; -- s->l1_entry_sectors = s->l2_size * s->cluster_sectors; -+ } -+ extent = vmdk_add_extent(bs, bs->file, false, -+ le32_to_cpu(header.disk_sectors), -+ le32_to_cpu(header.l1dir_offset) << 9, 0, -+ 1 << 6, 1 << 9, le32_to_cpu(header.granularity)); - } else if (magic == VMDK4_MAGIC) { - VMDK4Header header; -- -- if (bdrv_pread(bs->file, sizeof(magic), &header, sizeof(header)) != sizeof(header)) -+ if (bdrv_pread(bs->file, sizeof(magic), &header, sizeof(header)) -+ != sizeof(header)) { - goto fail; -- bs->total_sectors = le64_to_cpu(header.capacity); -- s->cluster_sectors = le64_to_cpu(header.granularity); -- s->l2_size = le32_to_cpu(header.num_gtes_per_gte); -- s->l1_entry_sectors = s->l2_size * s->cluster_sectors; -- if (s->l1_entry_sectors <= 0) -+ } -+ l1_entry_sectors = le32_to_cpu(header.num_gtes_per_gte) -+ * le64_to_cpu(header.granularity); -+ l1_size = (le64_to_cpu(header.capacity) + l1_entry_sectors - 1) -+ / l1_entry_sectors; -+ extent = vmdk_add_extent(bs, bs->file, false, -+ le64_to_cpu(header.capacity), -+ le64_to_cpu(header.gd_offset) << 9, -+ le64_to_cpu(header.rgd_offset) << 9, -+ l1_size, -+ le32_to_cpu(header.num_gtes_per_gte), -+ le64_to_cpu(header.granularity)); -+ if (extent->l1_entry_sectors <= 0) { - goto fail; -- s->l1_size = (bs->total_sectors + s->l1_entry_sectors - 1) -- / s->l1_entry_sectors; -- s->l1_table_offset = le64_to_cpu(header.rgd_offset) << 9; -- s->l1_backup_table_offset = le64_to_cpu(header.gd_offset) << 9; -- -+ } - // try to open parent images, if exist - if (vmdk_parent_open(bs) != 0) - goto fail; -@@ -406,40 +470,49 @@ static int vmdk_open(BlockDriverState *b - } - - /* read the L1 table */ -- l1_size = s->l1_size * sizeof(uint32_t); -- s->l1_table = qemu_malloc(l1_size); -- if (bdrv_pread(bs->file, s->l1_table_offset, s->l1_table, l1_size) != l1_size) -- goto fail; -- for(i = 0; i < s->l1_size; i++) { -- le32_to_cpus(&s->l1_table[i]); -- } -- -- if (s->l1_backup_table_offset) { -- s->l1_backup_table = qemu_malloc(l1_size); -- if (bdrv_pread(bs->file, s->l1_backup_table_offset, s->l1_backup_table, l1_size) != l1_size) -+ l1_size = extent->l1_size * sizeof(uint32_t); -+ extent->l1_table = qemu_malloc(l1_size); -+ if (bdrv_pread(bs->file, -+ extent->l1_table_offset, -+ extent->l1_table, -+ l1_size) -+ != l1_size) { -+ goto fail; -+ } -+ for (i = 0; i < extent->l1_size; i++) { -+ le32_to_cpus(&extent->l1_table[i]); -+ } -+ -+ if (extent->l1_backup_table_offset) { -+ extent->l1_backup_table = qemu_malloc(l1_size); -+ if (bdrv_pread(bs->file, -+ extent->l1_backup_table_offset, -+ extent->l1_backup_table, -+ l1_size) -+ != l1_size) { - goto fail; -- for(i = 0; i < s->l1_size; i++) { -- le32_to_cpus(&s->l1_backup_table[i]); -+ } -+ for (i = 0; i < extent->l1_size; i++) { -+ le32_to_cpus(&extent->l1_backup_table[i]); - } - } - -- s->l2_cache = qemu_malloc(s->l2_size * L2_CACHE_SIZE * sizeof(uint32_t)); -+ extent->l2_cache = -+ qemu_malloc(extent->l2_size * L2_CACHE_SIZE * sizeof(uint32_t)); - return 0; - fail: -- qemu_free(s->l1_backup_table); -- qemu_free(s->l1_table); -- qemu_free(s->l2_cache); -+ vmdk_free_extents(bs); - return -1; - } - --static uint64_t get_cluster_offset(BlockDriverState *bs, VmdkMetaData *m_data, -- uint64_t offset, int allocate); -- --static int get_whole_cluster(BlockDriverState *bs, uint64_t cluster_offset, -- uint64_t offset, int allocate) -+static int get_whole_cluster(BlockDriverState *bs, -+ VmdkExtent *extent, -+ uint64_t cluster_offset, -+ uint64_t offset, -+ bool allocate) - { -- BDRVVmdkState *s = bs->opaque; -- uint8_t whole_grain[s->cluster_sectors*512]; // 128 sectors * 512 bytes each = grain size 64KB -+ /* 128 sectors * 512 bytes each = grain size 64KB */ -+ uint8_t whole_grain[extent->cluster_sectors * 512]; - - // we will be here if it's first write on non-exist grain(cluster). - // try to read from parent image, if exist -@@ -450,14 +523,14 @@ static int get_whole_cluster(BlockDriver - return -1; - - ret = bdrv_read(bs->backing_hd, offset >> 9, whole_grain, -- s->cluster_sectors); -+ extent->cluster_sectors); - if (ret < 0) { - return -1; - } - - //Write grain only into the active image -- ret = bdrv_write(bs->file, cluster_offset, whole_grain, -- s->cluster_sectors); -+ ret = bdrv_write(extent->file, cluster_offset, whole_grain, -+ extent->cluster_sectors); - if (ret < 0) { - return -1; - } -@@ -465,29 +538,39 @@ static int get_whole_cluster(BlockDriver - return 0; - } - --static int vmdk_L2update(BlockDriverState *bs, VmdkMetaData *m_data) -+static int vmdk_L2update(VmdkExtent *extent, VmdkMetaData *m_data) - { -- BDRVVmdkState *s = bs->opaque; -- - /* update L2 table */ -- if (bdrv_pwrite_sync(bs->file, ((int64_t)m_data->l2_offset * 512) + (m_data->l2_index * sizeof(m_data->offset)), -- &(m_data->offset), sizeof(m_data->offset)) < 0) -+ if (bdrv_pwrite_sync( -+ extent->file, -+ ((int64_t)m_data->l2_offset * 512) -+ + (m_data->l2_index * sizeof(m_data->offset)), -+ &(m_data->offset), -+ sizeof(m_data->offset) -+ ) < 0) { - return -1; -+ } - /* update backup L2 table */ -- if (s->l1_backup_table_offset != 0) { -- m_data->l2_offset = s->l1_backup_table[m_data->l1_index]; -- if (bdrv_pwrite_sync(bs->file, ((int64_t)m_data->l2_offset * 512) + (m_data->l2_index * sizeof(m_data->offset)), -- &(m_data->offset), sizeof(m_data->offset)) < 0) -+ if (extent->l1_backup_table_offset != 0) { -+ m_data->l2_offset = extent->l1_backup_table[m_data->l1_index]; -+ if (bdrv_pwrite_sync( -+ extent->file, -+ ((int64_t)m_data->l2_offset * 512) -+ + (m_data->l2_index * sizeof(m_data->offset)), -+ &(m_data->offset), sizeof(m_data->offset) -+ ) < 0) { - return -1; -+ } - } - - return 0; - } - --static uint64_t get_cluster_offset(BlockDriverState *bs, VmdkMetaData *m_data, -- uint64_t offset, int allocate) -+static uint64_t get_cluster_offset(BlockDriverState *bs, -+ VmdkExtent *extent, -+ VmdkMetaData *m_data, -+ uint64_t offset, int allocate) - { -- BDRVVmdkState *s = bs->opaque; - unsigned int l1_index, l2_offset, l2_index; - int min_index, i, j; - uint32_t min_count, *l2_table, tmp = 0; -@@ -496,21 +579,23 @@ static uint64_t get_cluster_offset(Block - if (m_data) - m_data->valid = 0; - -- l1_index = (offset >> 9) / s->l1_entry_sectors; -- if (l1_index >= s->l1_size) -+ l1_index = (offset >> 9) / extent->l1_entry_sectors; -+ if (l1_index >= extent->l1_size) { - return 0; -- l2_offset = s->l1_table[l1_index]; -- if (!l2_offset) -+ } -+ l2_offset = extent->l1_table[l1_index]; -+ if (!l2_offset) { - return 0; -+ } - for(i = 0; i < L2_CACHE_SIZE; i++) { -- if (l2_offset == s->l2_cache_offsets[i]) { -+ if (l2_offset == extent->l2_cache_offsets[i]) { - /* increment the hit count */ -- if (++s->l2_cache_counts[i] == 0xffffffff) { -+ if (++extent->l2_cache_counts[i] == 0xffffffff) { - for(j = 0; j < L2_CACHE_SIZE; j++) { -- s->l2_cache_counts[j] >>= 1; -+ extent->l2_cache_counts[j] >>= 1; - } - } -- l2_table = s->l2_cache + (i * s->l2_size); -+ l2_table = extent->l2_cache + (i * extent->l2_size); - goto found; - } - } -@@ -518,20 +603,25 @@ static uint64_t get_cluster_offset(Block - min_index = 0; - min_count = 0xffffffff; - for(i = 0; i < L2_CACHE_SIZE; i++) { -- if (s->l2_cache_counts[i] < min_count) { -- min_count = s->l2_cache_counts[i]; -+ if (extent->l2_cache_counts[i] < min_count) { -+ min_count = extent->l2_cache_counts[i]; - min_index = i; - } - } -- l2_table = s->l2_cache + (min_index * s->l2_size); -- if (bdrv_pread(bs->file, (int64_t)l2_offset * 512, l2_table, s->l2_size * sizeof(uint32_t)) != -- s->l2_size * sizeof(uint32_t)) -+ l2_table = extent->l2_cache + (min_index * extent->l2_size); -+ if (bdrv_pread( -+ extent->file, -+ (int64_t)l2_offset * 512, -+ l2_table, -+ extent->l2_size * sizeof(uint32_t) -+ ) != extent->l2_size * sizeof(uint32_t)) { - return 0; -+ } - -- s->l2_cache_offsets[min_index] = l2_offset; -- s->l2_cache_counts[min_index] = 1; -+ extent->l2_cache_offsets[min_index] = l2_offset; -+ extent->l2_cache_counts[min_index] = 1; - found: -- l2_index = ((offset >> 9) / s->cluster_sectors) % s->l2_size; -+ l2_index = ((offset >> 9) / extent->cluster_sectors) % extent->l2_size; - cluster_offset = le32_to_cpu(l2_table[l2_index]); - - if (!cluster_offset) { -@@ -539,8 +629,11 @@ static uint64_t get_cluster_offset(Block - return 0; - - // Avoid the L2 tables update for the images that have snapshots. -- cluster_offset = bdrv_getlength(bs->file); -- bdrv_truncate(bs->file, cluster_offset + (s->cluster_sectors << 9)); -+ cluster_offset = bdrv_getlength(extent->file); -+ bdrv_truncate( -+ extent->file, -+ cluster_offset + (extent->cluster_sectors << 9) -+ ); - - cluster_offset >>= 9; - tmp = cpu_to_le32(cluster_offset); -@@ -551,7 +644,8 @@ static uint64_t get_cluster_offset(Block - * This problem may occur because of insufficient space on host disk - * or inappropriate VM shutdown. - */ -- if (get_whole_cluster(bs, cluster_offset, offset, allocate) == -1) -+ if (get_whole_cluster( -+ bs, extent, cluster_offset, offset, allocate) == -1) - return 0; - - if (m_data) { -@@ -566,33 +660,69 @@ static uint64_t get_cluster_offset(Block - return cluster_offset; - } - -+static VmdkExtent *find_extent(BDRVVmdkState *s, -+ int64_t sector_num, VmdkExtent *start_hint) -+{ -+ VmdkExtent *extent = start_hint; -+ -+ if (!extent) { -+ extent = &s->extents[0]; -+ } -+ while (extent < &s->extents[s->num_extents]) { -+ if (sector_num < extent->end_sector) { -+ return extent; -+ } -+ extent++; -+ } -+ return NULL; -+} -+ - static int vmdk_is_allocated(BlockDriverState *bs, int64_t sector_num, - int nb_sectors, int *pnum) - { - BDRVVmdkState *s = bs->opaque; -- int index_in_cluster, n; -- uint64_t cluster_offset; - -- cluster_offset = get_cluster_offset(bs, NULL, sector_num << 9, 0); -- index_in_cluster = sector_num % s->cluster_sectors; -- n = s->cluster_sectors - index_in_cluster; -+ int64_t index_in_cluster, n, ret; -+ uint64_t offset; -+ VmdkExtent *extent; -+ -+ extent = find_extent(s, sector_num, NULL); -+ if (!extent) { -+ return 0; -+ } -+ if (extent->flat) { -+ n = extent->end_sector - sector_num; -+ ret = 1; -+ } else { -+ offset = get_cluster_offset(bs, extent, NULL, sector_num * 512, 0); -+ index_in_cluster = sector_num % extent->cluster_sectors; -+ n = extent->cluster_sectors - index_in_cluster; -+ ret = offset ? 1 : 0; -+ } - if (n > nb_sectors) - n = nb_sectors; - *pnum = n; -- return (cluster_offset != 0); -+ return ret; - } - - static int vmdk_read(BlockDriverState *bs, int64_t sector_num, - uint8_t *buf, int nb_sectors) - { - BDRVVmdkState *s = bs->opaque; -- int index_in_cluster, n, ret; -+ int ret; -+ uint64_t n, index_in_cluster; -+ VmdkExtent *extent = NULL; - uint64_t cluster_offset; - - while (nb_sectors > 0) { -- cluster_offset = get_cluster_offset(bs, NULL, sector_num << 9, 0); -- index_in_cluster = sector_num % s->cluster_sectors; -- n = s->cluster_sectors - index_in_cluster; -+ extent = find_extent(s, sector_num, extent); -+ if (!extent) { -+ return -EIO; -+ } -+ cluster_offset = get_cluster_offset( -+ bs, extent, NULL, sector_num << 9, 0); -+ index_in_cluster = sector_num % extent->cluster_sectors; -+ n = extent->cluster_sectors - index_in_cluster; - if (n > nb_sectors) - n = nb_sectors; - if (!cluster_offset) { -@@ -621,10 +751,12 @@ static int vmdk_write(BlockDriverState * - const uint8_t *buf, int nb_sectors) - { - BDRVVmdkState *s = bs->opaque; -- VmdkMetaData m_data; -- int index_in_cluster, n; -+ VmdkExtent *extent = NULL; -+ int n; -+ int64_t index_in_cluster; - uint64_t cluster_offset; - static int cid_update = 0; -+ VmdkMetaData m_data; - - if (sector_num > bs->total_sectors) { - fprintf(stderr, -@@ -635,20 +767,35 @@ static int vmdk_write(BlockDriverState * - } - - while (nb_sectors > 0) { -- index_in_cluster = sector_num & (s->cluster_sectors - 1); -- n = s->cluster_sectors - index_in_cluster; -- if (n > nb_sectors) -- n = nb_sectors; -- cluster_offset = get_cluster_offset(bs, &m_data, sector_num << 9, 1); -- if (!cluster_offset) -+ extent = find_extent(s, sector_num, extent); -+ if (!extent) { -+ return -EIO; -+ } -+ cluster_offset = get_cluster_offset( -+ bs, -+ extent, -+ &m_data, -+ sector_num << 9, 1); -+ if (!cluster_offset) { - return -1; -+ } -+ index_in_cluster = sector_num % extent->cluster_sectors; -+ n = extent->cluster_sectors - index_in_cluster; -+ if (n > nb_sectors) { -+ n = nb_sectors; -+ } - -- if (bdrv_pwrite(bs->file, cluster_offset + index_in_cluster * 512, buf, n * 512) != n * 512) -+ if (bdrv_pwrite(bs->file, -+ cluster_offset + index_in_cluster * 512, -+ buf, n * 512) -+ != n * 512) { - return -1; -+ } - if (m_data.valid) { - /* update L2 tables */ -- if (vmdk_L2update(bs, &m_data) == -1) -+ if (vmdk_L2update(extent, &m_data) == -1) { - return -1; -+ } - } - nb_sectors -= n; - sector_num += n; -@@ -822,10 +969,7 @@ exit: - - static void vmdk_close(BlockDriverState *bs) - { -- BDRVVmdkState *s = bs->opaque; -- -- qemu_free(s->l1_table); -- qemu_free(s->l2_cache); -+ vmdk_free_extents(bs); - } - - static int vmdk_flush(BlockDriverState *bs) diff --git a/tools/qemu/patches/0003-VMDK-bugfix-align-offset-to-cluster-in-get_whole_clu.patch b/tools/qemu/patches/0003-VMDK-bugfix-align-offset-to-cluster-in-get_whole_clu.patch deleted file mode 100644 index 38e6c0ae8f..0000000000 --- a/tools/qemu/patches/0003-VMDK-bugfix-align-offset-to-cluster-in-get_whole_clu.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 66922efc83a670178b208dec2f5123ec85fb6ba3 Mon Sep 17 00:00:00 2001 -From: Fam Zheng <famcool@gmail.com> -Date: Tue, 12 Jul 2011 19:56:29 +0800 -Subject: [PATCH 03/12] VMDK: bugfix, align offset to cluster in - get_whole_cluster - -In get_whole_cluster, the offset is not aligned to cluster when reading -from backing_hd. When the first write to child is not at the cluster -boundary, wrong address data from parent is copied to child. - -Signed-off-by: Fam Zheng <famcool@gmail.com> -Reviewed-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com> -Signed-off-by: Kevin Wolf <kwolf@redhat.com> ---- - block/vmdk.c | 8 +++++--- - 1 file changed, 5 insertions(+), 3 deletions(-) - ---- a/block/vmdk.c -+++ b/block/vmdk.c -@@ -514,21 +514,23 @@ static int get_whole_cluster(BlockDriver - /* 128 sectors * 512 bytes each = grain size 64KB */ - uint8_t whole_grain[extent->cluster_sectors * 512]; - -- // we will be here if it's first write on non-exist grain(cluster). -- // try to read from parent image, if exist -+ /* we will be here if it's first write on non-exist grain(cluster). -+ * try to read from parent image, if exist */ - if (bs->backing_hd) { - int ret; - - if (!vmdk_is_cid_valid(bs)) - return -1; - -+ /* floor offset to cluster */ -+ offset -= offset % (extent->cluster_sectors * 512); - ret = bdrv_read(bs->backing_hd, offset >> 9, whole_grain, - extent->cluster_sectors); - if (ret < 0) { - return -1; - } - -- //Write grain only into the active image -+ /* Write grain only into the active image */ - ret = bdrv_write(extent->file, cluster_offset, whole_grain, - extent->cluster_sectors); - if (ret < 0) { diff --git a/tools/qemu/patches/0004-VMDK-probe-for-monolithicFlat-images.patch b/tools/qemu/patches/0004-VMDK-probe-for-monolithicFlat-images.patch deleted file mode 100644 index 86451ea24d..0000000000 --- a/tools/qemu/patches/0004-VMDK-probe-for-monolithicFlat-images.patch +++ /dev/null @@ -1,74 +0,0 @@ -From 930e57ecb64bbab75c2b71d0d1ba07451fec4567 Mon Sep 17 00:00:00 2001 -From: Fam Zheng <famcool@gmail.com> -Date: Tue, 12 Jul 2011 19:56:30 +0800 -Subject: [PATCH 04/12] VMDK: probe for monolithicFlat images - -Probe as the same behavior as VMware does. -Recognize image as monolithicFlat descriptor file when the file is text -and the first effective line (not '#' leaded comment or space line) is -either 'version=1' or 'version=2'. No space or upper case charactors -accepted. - -Signed-off-by: Fam Zheng <famcool@gmail.com> -Reviewed-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com> -Signed-off-by: Kevin Wolf <kwolf@redhat.com> ---- - block/vmdk.c | 45 +++++++++++++++++++++++++++++++++++++++++++-- - 1 file changed, 43 insertions(+), 2 deletions(-) - ---- a/block/vmdk.c -+++ b/block/vmdk.c -@@ -103,10 +103,51 @@ static int vmdk_probe(const uint8_t *buf - return 0; - magic = be32_to_cpu(*(uint32_t *)buf); - if (magic == VMDK3_MAGIC || -- magic == VMDK4_MAGIC) -+ magic == VMDK4_MAGIC) { - return 100; -- else -+ } else { -+ const char *p = (const char *)buf; -+ const char *end = p + buf_size; -+ while (p < end) { -+ if (*p == '#') { -+ /* skip comment line */ -+ while (p < end && *p != '\n') { -+ p++; -+ } -+ p++; -+ continue; -+ } -+ if (*p == ' ') { -+ while (p < end && *p == ' ') { -+ p++; -+ } -+ /* skip '\r' if windows line endings used. */ -+ if (p < end && *p == '\r') { -+ p++; -+ } -+ /* only accept blank lines before 'version=' line */ -+ if (p == end || *p != '\n') { -+ return 0; -+ } -+ p++; -+ continue; -+ } -+ if (end - p >= strlen("version=X\n")) { -+ if (strncmp("version=1\n", p, strlen("version=1\n")) == 0 || -+ strncmp("version=2\n", p, strlen("version=2\n")) == 0) { -+ return 100; -+ } -+ } -+ if (end - p >= strlen("version=X\r\n")) { -+ if (strncmp("version=1\r\n", p, strlen("version=1\r\n")) == 0 || -+ strncmp("version=2\r\n", p, strlen("version=2\r\n")) == 0) { -+ return 100; -+ } -+ } -+ return 0; -+ } - return 0; -+ } - } - - #define CHECK_CID 1 diff --git a/tools/qemu/patches/0005-VMDK-separate-vmdk_open-by-format-version.patch b/tools/qemu/patches/0005-VMDK-separate-vmdk_open-by-format-version.patch deleted file mode 100644 index 7323aa13be..0000000000 --- a/tools/qemu/patches/0005-VMDK-separate-vmdk_open-by-format-version.patch +++ /dev/null @@ -1,241 +0,0 @@ -From 97cf5df76657bab81d6b8669607f6f13215201c1 Mon Sep 17 00:00:00 2001 -From: Fam Zheng <famcool@gmail.com> -Date: Tue, 12 Jul 2011 19:56:31 +0800 -Subject: [PATCH 05/12] VMDK: separate vmdk_open by format version - -Separate vmdk_open by subformats to: -* vmdk_open_vmdk3 -* vmdk_open_vmdk4 - -Signed-off-by: Fam Zheng <famcool@gmail.com> -Reviewed-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com> -Signed-off-by: Kevin Wolf <kwolf@redhat.com> ---- - block/vmdk.c | 178 +++++++++++++++++++++++++++++++++++++---------------------- - 1 file changed, 112 insertions(+), 66 deletions(-) - ---- a/block/vmdk.c -+++ b/block/vmdk.c -@@ -458,67 +458,20 @@ static VmdkExtent *vmdk_add_extent(Block - return extent; - } - -- --static int vmdk_open(BlockDriverState *bs, int flags) -+static int vmdk_init_tables(BlockDriverState *bs, VmdkExtent *extent) - { -- BDRVVmdkState *s = bs->opaque; -- uint32_t magic; -- int i; -- uint32_t l1_size, l1_entry_sectors; -- VmdkExtent *extent = NULL; -- -- if (bdrv_pread(bs->file, 0, &magic, sizeof(magic)) != sizeof(magic)) -- goto fail; -- -- magic = be32_to_cpu(magic); -- if (magic == VMDK3_MAGIC) { -- VMDK3Header header; -- if (bdrv_pread(bs->file, sizeof(magic), &header, sizeof(header)) -- != sizeof(header)) { -- goto fail; -- } -- extent = vmdk_add_extent(bs, bs->file, false, -- le32_to_cpu(header.disk_sectors), -- le32_to_cpu(header.l1dir_offset) << 9, 0, -- 1 << 6, 1 << 9, le32_to_cpu(header.granularity)); -- } else if (magic == VMDK4_MAGIC) { -- VMDK4Header header; -- if (bdrv_pread(bs->file, sizeof(magic), &header, sizeof(header)) -- != sizeof(header)) { -- goto fail; -- } -- l1_entry_sectors = le32_to_cpu(header.num_gtes_per_gte) -- * le64_to_cpu(header.granularity); -- l1_size = (le64_to_cpu(header.capacity) + l1_entry_sectors - 1) -- / l1_entry_sectors; -- extent = vmdk_add_extent(bs, bs->file, false, -- le64_to_cpu(header.capacity), -- le64_to_cpu(header.gd_offset) << 9, -- le64_to_cpu(header.rgd_offset) << 9, -- l1_size, -- le32_to_cpu(header.num_gtes_per_gte), -- le64_to_cpu(header.granularity)); -- if (extent->l1_entry_sectors <= 0) { -- goto fail; -- } -- // try to open parent images, if exist -- if (vmdk_parent_open(bs) != 0) -- goto fail; -- // write the CID once after the image creation -- s->parent_cid = vmdk_read_cid(bs,1); -- } else { -- goto fail; -- } -+ int ret; -+ int l1_size, i; - - /* read the L1 table */ - l1_size = extent->l1_size * sizeof(uint32_t); - extent->l1_table = qemu_malloc(l1_size); -- if (bdrv_pread(bs->file, -- extent->l1_table_offset, -- extent->l1_table, -- l1_size) -- != l1_size) { -- goto fail; -+ ret = bdrv_pread(extent->file, -+ extent->l1_table_offset, -+ extent->l1_table, -+ l1_size); -+ if (ret < 0) { -+ goto fail_l1; - } - for (i = 0; i < extent->l1_size; i++) { - le32_to_cpus(&extent->l1_table[i]); -@@ -526,12 +479,12 @@ static int vmdk_open(BlockDriverState *b - - if (extent->l1_backup_table_offset) { - extent->l1_backup_table = qemu_malloc(l1_size); -- if (bdrv_pread(bs->file, -- extent->l1_backup_table_offset, -- extent->l1_backup_table, -- l1_size) -- != l1_size) { -- goto fail; -+ ret = bdrv_pread(extent->file, -+ extent->l1_backup_table_offset, -+ extent->l1_backup_table, -+ l1_size); -+ if (ret < 0) { -+ goto fail_l1b; - } - for (i = 0; i < extent->l1_size; i++) { - le32_to_cpus(&extent->l1_backup_table[i]); -@@ -541,9 +494,102 @@ static int vmdk_open(BlockDriverState *b - extent->l2_cache = - qemu_malloc(extent->l2_size * L2_CACHE_SIZE * sizeof(uint32_t)); - return 0; -+ fail_l1b: -+ qemu_free(extent->l1_backup_table); -+ fail_l1: -+ qemu_free(extent->l1_table); -+ return ret; -+} -+ -+static int vmdk_open_vmdk3(BlockDriverState *bs, int flags) -+{ -+ int ret; -+ uint32_t magic; -+ VMDK3Header header; -+ VmdkExtent *extent; -+ -+ ret = bdrv_pread(bs->file, sizeof(magic), &header, sizeof(header)); -+ if (ret < 0) { -+ goto fail; -+ } -+ extent = vmdk_add_extent(bs, -+ bs->file, false, -+ le32_to_cpu(header.disk_sectors), -+ le32_to_cpu(header.l1dir_offset) << 9, -+ 0, 1 << 6, 1 << 9, -+ le32_to_cpu(header.granularity)); -+ ret = vmdk_init_tables(bs, extent); -+ if (ret) { -+ /* vmdk_init_tables cleans up on fail, so only free allocation of -+ * vmdk_add_extent here. */ -+ goto fail; -+ } -+ return 0; - fail: - vmdk_free_extents(bs); -- return -1; -+ return ret; -+} -+ -+static int vmdk_open_vmdk4(BlockDriverState *bs, int flags) -+{ -+ int ret; -+ uint32_t magic; -+ uint32_t l1_size, l1_entry_sectors; -+ VMDK4Header header; -+ BDRVVmdkState *s = bs->opaque; -+ VmdkExtent *extent; -+ -+ ret = bdrv_pread(bs->file, sizeof(magic), &header, sizeof(header)); -+ if (ret < 0) { -+ goto fail; -+ } -+ l1_entry_sectors = le32_to_cpu(header.num_gtes_per_gte) -+ * le64_to_cpu(header.granularity); -+ l1_size = (le64_to_cpu(header.capacity) + l1_entry_sectors - 1) -+ / l1_entry_sectors; -+ extent = vmdk_add_extent(bs, bs->file, false, -+ le64_to_cpu(header.capacity), -+ le64_to_cpu(header.gd_offset) << 9, -+ le64_to_cpu(header.rgd_offset) << 9, -+ l1_size, -+ le32_to_cpu(header.num_gtes_per_gte), -+ le64_to_cpu(header.granularity)); -+ if (extent->l1_entry_sectors <= 0) { -+ ret = -EINVAL; -+ goto fail; -+ } -+ /* try to open parent images, if exist */ -+ ret = vmdk_parent_open(bs); -+ if (ret) { -+ goto fail; -+ } -+ s->parent_cid = vmdk_read_cid(bs, 1); -+ ret = vmdk_init_tables(bs, extent); -+ if (ret) { -+ goto fail; -+ } -+ return 0; -+ fail: -+ vmdk_free_extents(bs); -+ return ret; -+} -+ -+static int vmdk_open(BlockDriverState *bs, int flags) -+{ -+ uint32_t magic; -+ -+ if (bdrv_pread(bs->file, 0, &magic, sizeof(magic)) != sizeof(magic)) { -+ return -EIO; -+ } -+ -+ magic = be32_to_cpu(magic); -+ if (magic == VMDK3_MAGIC) { -+ return vmdk_open_vmdk3(bs, flags); -+ } else if (magic == VMDK4_MAGIC) { -+ return vmdk_open_vmdk4(bs, flags); -+ } else { -+ return -EINVAL; -+ } - } - - static int get_whole_cluster(BlockDriverState *bs, -@@ -630,11 +676,11 @@ static uint64_t get_cluster_offset(Block - if (!l2_offset) { - return 0; - } -- for(i = 0; i < L2_CACHE_SIZE; i++) { -+ for (i = 0; i < L2_CACHE_SIZE; i++) { - if (l2_offset == extent->l2_cache_offsets[i]) { - /* increment the hit count */ - if (++extent->l2_cache_counts[i] == 0xffffffff) { -- for(j = 0; j < L2_CACHE_SIZE; j++) { -+ for (j = 0; j < L2_CACHE_SIZE; j++) { - extent->l2_cache_counts[j] >>= 1; - } - } -@@ -645,7 +691,7 @@ static uint64_t get_cluster_offset(Block - /* not found: load a new entry in the least used one */ - min_index = 0; - min_count = 0xffffffff; -- for(i = 0; i < L2_CACHE_SIZE; i++) { -+ for (i = 0; i < L2_CACHE_SIZE; i++) { - if (extent->l2_cache_counts[i] < min_count) { - min_count = extent->l2_cache_counts[i]; - min_index = i; diff --git a/tools/qemu/patches/0006-VMDK-add-field-BDRVVmdkState.desc_offset.patch b/tools/qemu/patches/0006-VMDK-add-field-BDRVVmdkState.desc_offset.patch deleted file mode 100644 index 51bbb3b010..0000000000 --- a/tools/qemu/patches/0006-VMDK-add-field-BDRVVmdkState.desc_offset.patch +++ /dev/null @@ -1,102 +0,0 @@ -From 1c1781fa1c45a7c012f7b2c4be1be372f19e3cc6 Mon Sep 17 00:00:00 2001 -From: Fam Zheng <famcool@gmail.com> -Date: Tue, 12 Jul 2011 19:56:32 +0800 -Subject: [PATCH 06/12] VMDK: add field BDRVVmdkState.desc_offset - -There are several occurrence of magic number 0x200 as the descriptor -offset within mono sparse image file. This is not the case for images -with separate descriptor file. So a field is added to BDRVVmdkState to -hold the correct value. - -Signed-off-by: Fam Zheng <famcool@gmail.com> -Reviewed-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com> -Signed-off-by: Kevin Wolf <kwolf@redhat.com> ---- - block/vmdk.c | 27 ++++++++++++++++++--------- - 1 file changed, 18 insertions(+), 9 deletions(-) - ---- a/block/vmdk.c -+++ b/block/vmdk.c -@@ -81,6 +81,7 @@ typedef struct VmdkExtent { - } VmdkExtent; - - typedef struct BDRVVmdkState { -+ int desc_offset; - uint32_t parent_cid; - int num_extents; - /* Extent array with num_extents entries, ascend ordered by address */ -@@ -175,10 +176,11 @@ static uint32_t vmdk_read_cid(BlockDrive - uint32_t cid; - const char *p_name, *cid_str; - size_t cid_str_size; -+ BDRVVmdkState *s = bs->opaque; - -- /* the descriptor offset = 0x200 */ -- if (bdrv_pread(bs->file, 0x200, desc, DESC_SIZE) != DESC_SIZE) -+ if (bdrv_pread(bs->file, s->desc_offset, desc, DESC_SIZE) != DESC_SIZE) { - return 0; -+ } - - if (parent) { - cid_str = "parentCID"; -@@ -200,10 +202,12 @@ static int vmdk_write_cid(BlockDriverSta - { - char desc[DESC_SIZE], tmp_desc[DESC_SIZE]; - char *p_name, *tmp_str; -+ BDRVVmdkState *s = bs->opaque; - -- /* the descriptor offset = 0x200 */ -- if (bdrv_pread(bs->file, 0x200, desc, DESC_SIZE) != DESC_SIZE) -- return -1; -+ memset(desc, 0, sizeof(desc)); -+ if (bdrv_pread(bs->file, s->desc_offset, desc, DESC_SIZE) != DESC_SIZE) { -+ return -EIO; -+ } - - tmp_str = strstr(desc,"parentCID"); - pstrcpy(tmp_desc, sizeof(tmp_desc), tmp_str); -@@ -213,8 +217,9 @@ static int vmdk_write_cid(BlockDriverSta - pstrcat(desc, sizeof(desc), tmp_desc); - } - -- if (bdrv_pwrite_sync(bs->file, 0x200, desc, DESC_SIZE) < 0) -- return -1; -+ if (bdrv_pwrite_sync(bs->file, s->desc_offset, desc, DESC_SIZE) < 0) { -+ return -EIO; -+ } - return 0; - } - -@@ -402,10 +407,11 @@ static int vmdk_parent_open(BlockDriverS - { - char *p_name; - char desc[DESC_SIZE]; -+ BDRVVmdkState *s = bs->opaque; - -- /* the descriptor offset = 0x200 */ -- if (bdrv_pread(bs->file, 0x200, desc, DESC_SIZE) != DESC_SIZE) -+ if (bdrv_pread(bs->file, s->desc_offset, desc, DESC_SIZE) != DESC_SIZE) { - return -1; -+ } - - if ((p_name = strstr(desc,"parentFileNameHint")) != NULL) { - char *end_name; -@@ -506,8 +512,10 @@ static int vmdk_open_vmdk3(BlockDriverSt - int ret; - uint32_t magic; - VMDK3Header header; -+ BDRVVmdkState *s = bs->opaque; - VmdkExtent *extent; - -+ s->desc_offset = 0x200; - ret = bdrv_pread(bs->file, sizeof(magic), &header, sizeof(header)); - if (ret < 0) { - goto fail; -@@ -539,6 +547,7 @@ static int vmdk_open_vmdk4(BlockDriverSt - BDRVVmdkState *s = bs->opaque; - VmdkExtent *extent; - -+ s->desc_offset = 0x200; - ret = bdrv_pread(bs->file, sizeof(magic), &header, sizeof(header)); - if (ret < 0) { - goto fail; diff --git a/tools/qemu/patches/0007-VMDK-flush-multiple-extents.patch b/tools/qemu/patches/0007-VMDK-flush-multiple-extents.patch deleted file mode 100644 index b228236517..0000000000 --- a/tools/qemu/patches/0007-VMDK-flush-multiple-extents.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 49885608e66c1e76a2b715fb36fd2f27f73e5202 Mon Sep 17 00:00:00 2001 -From: Fam Zheng <famcool@gmail.com> -Date: Tue, 12 Jul 2011 19:56:33 +0800 -Subject: [PATCH 07/12] VMDK: flush multiple extents - -Flush all the file that referenced by the image. - -Signed-off-by: Fam Zheng <famcool@gmail.com> -Reviewed-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com> -Signed-off-by: Kevin Wolf <kwolf@redhat.com> ---- - block/vmdk.c | 12 +++++++++++- - 1 file changed, 11 insertions(+), 1 deletion(-) - ---- a/block/vmdk.c -+++ b/block/vmdk.c -@@ -1072,7 +1072,17 @@ static void vmdk_close(BlockDriverState - - static int vmdk_flush(BlockDriverState *bs) - { -- return bdrv_flush(bs->file); -+ int i, ret, err; -+ BDRVVmdkState *s = bs->opaque; -+ -+ ret = bdrv_flush(bs->file); -+ for (i = 0; i < s->num_extents; i++) { -+ err = bdrv_flush(s->extents[i].file); -+ if (err < 0) { -+ ret = err; -+ } -+ } -+ return ret; - } - - diff --git a/tools/qemu/patches/0008-VMDK-move-static-cid_update-flag-to-bs-field.patch b/tools/qemu/patches/0008-VMDK-move-static-cid_update-flag-to-bs-field.patch deleted file mode 100644 index 90a699d73b..0000000000 --- a/tools/qemu/patches/0008-VMDK-move-static-cid_update-flag-to-bs-field.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 9d8117f00364c12cbd658de903b1ed26a30584e0 Mon Sep 17 00:00:00 2001 -From: Fam Zheng <famcool@gmail.com> -Date: Tue, 12 Jul 2011 19:56:34 +0800 -Subject: [PATCH 08/12] VMDK: move 'static' cid_update flag to bs field - -Cid_update is the flag for updating CID on first write after opening the -image. This should be per image open rather than per program life cycle, -so change it from static var of vmdk_write to a field in BDRVVmdkState. - -Signed-off-by: Fam Zheng <famcool@gmail.com> -Reviewed-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com> -Signed-off-by: Kevin Wolf <kwolf@redhat.com> ---- - block/vmdk.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - ---- a/block/vmdk.c -+++ b/block/vmdk.c -@@ -82,6 +82,7 @@ typedef struct VmdkExtent { - - typedef struct BDRVVmdkState { - int desc_offset; -+ bool cid_updated; - uint32_t parent_cid; - int num_extents; - /* Extent array with num_extents entries, ascend ordered by address */ -@@ -853,7 +854,6 @@ static int vmdk_write(BlockDriverState * - int n; - int64_t index_in_cluster; - uint64_t cluster_offset; -- static int cid_update = 0; - VmdkMetaData m_data; - - if (sector_num > bs->total_sectors) { -@@ -900,9 +900,9 @@ static int vmdk_write(BlockDriverState * - buf += n * 512; - - // update CID on the first write every time the virtual disk is opened -- if (!cid_update) { -+ if (!s->cid_updated) { - vmdk_write_cid(bs, time(NULL)); -- cid_update++; -+ s->cid_updated = true; - } - } - return 0; diff --git a/tools/qemu/patches/0009-VMDK-change-get_cluster_offset-return-type.patch b/tools/qemu/patches/0009-VMDK-change-get_cluster_offset-return-type.patch deleted file mode 100644 index bc6e74656e..0000000000 --- a/tools/qemu/patches/0009-VMDK-change-get_cluster_offset-return-type.patch +++ /dev/null @@ -1,198 +0,0 @@ -From 9e1ddc6967e8739f4fa47fa4f6a767ebe319f6ff Mon Sep 17 00:00:00 2001 -From: Fam Zheng <famcool@gmail.com> -Date: Tue, 12 Jul 2011 19:56:35 +0800 -Subject: [PATCH 09/12] VMDK: change get_cluster_offset return type - -The return type of get_cluster_offset was an offset that use 0 to denote -'not allocated', this will be no longer true for flat extents, as we see -flat extent file as a single huge cluster whose offset is 0 and length -is the whole file length. -So now we use int return value, 0 means success and otherwise offset -invalid. - -Signed-off-by: Fam Zheng <famcool@gmail.com> -Reviewed-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com> -Signed-off-by: Kevin Wolf <kwolf@redhat.com> ---- - block/vmdk.c | 79 ++++++++++++++++++++++++++++++++---------------------------- - 1 file changed, 42 insertions(+), 37 deletions(-) - ---- a/block/vmdk.c -+++ b/block/vmdk.c -@@ -665,26 +665,31 @@ static int vmdk_L2update(VmdkExtent *ext - return 0; - } - --static uint64_t get_cluster_offset(BlockDriverState *bs, -+static int get_cluster_offset(BlockDriverState *bs, - VmdkExtent *extent, - VmdkMetaData *m_data, -- uint64_t offset, int allocate) -+ uint64_t offset, -+ int allocate, -+ uint64_t *cluster_offset) - { - unsigned int l1_index, l2_offset, l2_index; - int min_index, i, j; - uint32_t min_count, *l2_table, tmp = 0; -- uint64_t cluster_offset; - - if (m_data) - m_data->valid = 0; -+ if (extent->flat) { -+ *cluster_offset = 0; -+ return 0; -+ } - - l1_index = (offset >> 9) / extent->l1_entry_sectors; - if (l1_index >= extent->l1_size) { -- return 0; -+ return -1; - } - l2_offset = extent->l1_table[l1_index]; - if (!l2_offset) { -- return 0; -+ return -1; - } - for (i = 0; i < L2_CACHE_SIZE; i++) { - if (l2_offset == extent->l2_cache_offsets[i]) { -@@ -714,28 +719,29 @@ static uint64_t get_cluster_offset(Block - l2_table, - extent->l2_size * sizeof(uint32_t) - ) != extent->l2_size * sizeof(uint32_t)) { -- return 0; -+ return -1; - } - - extent->l2_cache_offsets[min_index] = l2_offset; - extent->l2_cache_counts[min_index] = 1; - found: - l2_index = ((offset >> 9) / extent->cluster_sectors) % extent->l2_size; -- cluster_offset = le32_to_cpu(l2_table[l2_index]); -+ *cluster_offset = le32_to_cpu(l2_table[l2_index]); - -- if (!cluster_offset) { -- if (!allocate) -- return 0; -+ if (!*cluster_offset) { -+ if (!allocate) { -+ return -1; -+ } - - // Avoid the L2 tables update for the images that have snapshots. -- cluster_offset = bdrv_getlength(extent->file); -+ *cluster_offset = bdrv_getlength(extent->file); - bdrv_truncate( - extent->file, -- cluster_offset + (extent->cluster_sectors << 9) -+ *cluster_offset + (extent->cluster_sectors << 9) - ); - -- cluster_offset >>= 9; -- tmp = cpu_to_le32(cluster_offset); -+ *cluster_offset >>= 9; -+ tmp = cpu_to_le32(*cluster_offset); - l2_table[l2_index] = tmp; - - /* First of all we write grain itself, to avoid race condition -@@ -744,8 +750,8 @@ static uint64_t get_cluster_offset(Block - * or inappropriate VM shutdown. - */ - if (get_whole_cluster( -- bs, extent, cluster_offset, offset, allocate) == -1) -- return 0; -+ bs, extent, *cluster_offset, offset, allocate) == -1) -+ return -1; - - if (m_data) { - m_data->offset = tmp; -@@ -755,8 +761,8 @@ static uint64_t get_cluster_offset(Block - m_data->valid = 1; - } - } -- cluster_offset <<= 9; -- return cluster_offset; -+ *cluster_offset <<= 9; -+ return 0; - } - - static VmdkExtent *find_extent(BDRVVmdkState *s, -@@ -780,7 +786,6 @@ static int vmdk_is_allocated(BlockDriver - int nb_sectors, int *pnum) - { - BDRVVmdkState *s = bs->opaque; -- - int64_t index_in_cluster, n, ret; - uint64_t offset; - VmdkExtent *extent; -@@ -789,15 +794,13 @@ static int vmdk_is_allocated(BlockDriver - if (!extent) { - return 0; - } -- if (extent->flat) { -- n = extent->end_sector - sector_num; -- ret = 1; -- } else { -- offset = get_cluster_offset(bs, extent, NULL, sector_num * 512, 0); -- index_in_cluster = sector_num % extent->cluster_sectors; -- n = extent->cluster_sectors - index_in_cluster; -- ret = offset ? 1 : 0; -- } -+ ret = get_cluster_offset(bs, extent, NULL, -+ sector_num * 512, 0, &offset); -+ /* get_cluster_offset returning 0 means success */ -+ ret = !ret; -+ -+ index_in_cluster = sector_num % extent->cluster_sectors; -+ n = extent->cluster_sectors - index_in_cluster; - if (n > nb_sectors) - n = nb_sectors; - *pnum = n; -@@ -818,14 +821,15 @@ static int vmdk_read(BlockDriverState *b - if (!extent) { - return -EIO; - } -- cluster_offset = get_cluster_offset( -- bs, extent, NULL, sector_num << 9, 0); -+ ret = get_cluster_offset( -+ bs, extent, NULL, -+ sector_num << 9, 0, &cluster_offset); - index_in_cluster = sector_num % extent->cluster_sectors; - n = extent->cluster_sectors - index_in_cluster; - if (n > nb_sectors) - n = nb_sectors; -- if (!cluster_offset) { -- // try to read from parent image, if exist -+ if (ret) { -+ /* if not allocated, try to read from parent image, if exist */ - if (bs->backing_hd) { - if (!vmdk_is_cid_valid(bs)) - return -1; -@@ -851,7 +855,7 @@ static int vmdk_write(BlockDriverState * - { - BDRVVmdkState *s = bs->opaque; - VmdkExtent *extent = NULL; -- int n; -+ int n, ret; - int64_t index_in_cluster; - uint64_t cluster_offset; - VmdkMetaData m_data; -@@ -869,13 +873,14 @@ static int vmdk_write(BlockDriverState * - if (!extent) { - return -EIO; - } -- cluster_offset = get_cluster_offset( -+ ret = get_cluster_offset( - bs, - extent, - &m_data, -- sector_num << 9, 1); -- if (!cluster_offset) { -- return -1; -+ sector_num << 9, 1, -+ &cluster_offset); -+ if (ret) { -+ return -EINVAL; - } - index_in_cluster = sector_num % extent->cluster_sectors; - n = extent->cluster_sectors - index_in_cluster; diff --git a/tools/qemu/patches/0010-VMDK-open-read-write-for-monolithicFlat-image.patch b/tools/qemu/patches/0010-VMDK-open-read-write-for-monolithicFlat-image.patch deleted file mode 100644 index b05d0d37d8..0000000000 --- a/tools/qemu/patches/0010-VMDK-open-read-write-for-monolithicFlat-image.patch +++ /dev/null @@ -1,257 +0,0 @@ -From e6b783a12f7ff491a1a2147d9fe55b4535aa046e Mon Sep 17 00:00:00 2001 -From: Fam Zheng <famcool@gmail.com> -Date: Tue, 19 Jul 2011 08:38:22 +0800 -Subject: [PATCH 10/12] VMDK: open/read/write for monolithicFlat image - -Parse vmdk decriptor file and open mono flat image. -Read/write the flat extent. - -Signed-off-by: Fam Zheng <famcool@gmail.com> -Reviewed-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com> -Signed-off-by: Kevin Wolf <kwolf@redhat.com> ---- - block/vmdk.c | 171 ++++++++++++++++++++++++++++++++++++++++++++++++++++++----- - 1 file changed, 158 insertions(+), 13 deletions(-) - ---- a/block/vmdk.c -+++ b/block/vmdk.c -@@ -65,6 +65,7 @@ typedef struct VmdkExtent { - bool flat; - int64_t sectors; - int64_t end_sector; -+ int64_t flat_start_offset; - int64_t l1_table_offset; - int64_t l1_backup_table_offset; - uint32_t *l1_table; -@@ -407,9 +408,10 @@ fail: - static int vmdk_parent_open(BlockDriverState *bs) - { - char *p_name; -- char desc[DESC_SIZE]; -+ char desc[DESC_SIZE + 1]; - BDRVVmdkState *s = bs->opaque; - -+ desc[DESC_SIZE] = '\0'; - if (bdrv_pread(bs->file, s->desc_offset, desc, DESC_SIZE) != DESC_SIZE) { - return -1; - } -@@ -584,6 +586,144 @@ static int vmdk_open_vmdk4(BlockDriverSt - return ret; - } - -+/* find an option value out of descriptor file */ -+static int vmdk_parse_description(const char *desc, const char *opt_name, -+ char *buf, int buf_size) -+{ -+ char *opt_pos, *opt_end; -+ const char *end = desc + strlen(desc); -+ -+ opt_pos = strstr(desc, opt_name); -+ if (!opt_pos) { -+ return -1; -+ } -+ /* Skip "=\"" following opt_name */ -+ opt_pos += strlen(opt_name) + 2; -+ if (opt_pos >= end) { -+ return -1; -+ } -+ opt_end = opt_pos; -+ while (opt_end < end && *opt_end != '"') { -+ opt_end++; -+ } -+ if (opt_end == end || buf_size < opt_end - opt_pos + 1) { -+ return -1; -+ } -+ pstrcpy(buf, opt_end - opt_pos + 1, opt_pos); -+ return 0; -+} -+ -+static int vmdk_parse_extents(const char *desc, BlockDriverState *bs, -+ const char *desc_file_path) -+{ -+ int ret; -+ char access[11]; -+ char type[11]; -+ char fname[512]; -+ const char *p = desc; -+ int64_t sectors = 0; -+ int64_t flat_offset; -+ -+ while (*p) { -+ /* parse extent line: -+ * RW [size in sectors] FLAT "file-name.vmdk" OFFSET -+ * or -+ * RW [size in sectors] SPARSE "file-name.vmdk" -+ */ -+ flat_offset = -1; -+ ret = sscanf(p, "%10s %" SCNd64 " %10s %511s %" SCNd64, -+ access, §ors, type, fname, &flat_offset); -+ if (ret < 4 || strcmp(access, "RW")) { -+ goto next_line; -+ } else if (!strcmp(type, "FLAT")) { -+ if (ret != 5 || flat_offset < 0) { -+ return -EINVAL; -+ } -+ } else if (ret != 4) { -+ return -EINVAL; -+ } -+ -+ /* trim the quotation marks around */ -+ if (fname[0] == '"') { -+ memmove(fname, fname + 1, strlen(fname)); -+ if (strlen(fname) <= 1 || fname[strlen(fname) - 1] != '"') { -+ return -EINVAL; -+ } -+ fname[strlen(fname) - 1] = '\0'; -+ } -+ if (sectors <= 0 || -+ (strcmp(type, "FLAT") && strcmp(type, "SPARSE")) || -+ (strcmp(access, "RW"))) { -+ goto next_line; -+ } -+ -+ /* save to extents array */ -+ if (!strcmp(type, "FLAT")) { -+ /* FLAT extent */ -+ char extent_path[PATH_MAX]; -+ BlockDriverState *extent_file; -+ VmdkExtent *extent; -+ -+ path_combine(extent_path, sizeof(extent_path), -+ desc_file_path, fname); -+ ret = bdrv_file_open(&extent_file, extent_path, bs->open_flags); -+ if (ret) { -+ return ret; -+ } -+ extent = vmdk_add_extent(bs, extent_file, true, sectors, -+ 0, 0, 0, 0, sectors); -+ extent->flat_start_offset = flat_offset; -+ } else { -+ /* SPARSE extent, not supported for now */ -+ fprintf(stderr, -+ "VMDK: Not supported extent type \"%s\""".\n", type); -+ return -ENOTSUP; -+ } -+next_line: -+ /* move to next line */ -+ while (*p && *p != '\n') { -+ p++; -+ } -+ p++; -+ } -+ return 0; -+} -+ -+static int vmdk_open_desc_file(BlockDriverState *bs, int flags) -+{ -+ int ret; -+ char buf[2048]; -+ char ct[128]; -+ BDRVVmdkState *s = bs->opaque; -+ -+ ret = bdrv_pread(bs->file, 0, buf, sizeof(buf)); -+ if (ret < 0) { -+ return ret; -+ } -+ buf[2047] = '\0'; -+ if (vmdk_parse_description(buf, "createType", ct, sizeof(ct))) { -+ return -EINVAL; -+ } -+ if (strcmp(ct, "monolithicFlat")) { -+ fprintf(stderr, -+ "VMDK: Not supported image type \"%s\""".\n", ct); -+ return -ENOTSUP; -+ } -+ s->desc_offset = 0; -+ ret = vmdk_parse_extents(buf, bs, bs->file->filename); -+ if (ret) { -+ return ret; -+ } -+ -+ /* try to open parent images, if exist */ -+ if (vmdk_parent_open(bs)) { -+ qemu_free(s->extents); -+ return -EINVAL; -+ } -+ s->parent_cid = vmdk_read_cid(bs, 1); -+ return 0; -+} -+ - static int vmdk_open(BlockDriverState *bs, int flags) - { - uint32_t magic; -@@ -598,7 +738,7 @@ static int vmdk_open(BlockDriverState *b - } else if (magic == VMDK4_MAGIC) { - return vmdk_open_vmdk4(bs, flags); - } else { -- return -EINVAL; -+ return vmdk_open_desc_file(bs, flags); - } - } - -@@ -679,7 +819,7 @@ static int get_cluster_offset(BlockDrive - if (m_data) - m_data->valid = 0; - if (extent->flat) { -- *cluster_offset = 0; -+ *cluster_offset = extent->flat_start_offset; - return 0; - } - -@@ -832,16 +972,20 @@ static int vmdk_read(BlockDriverState *b - /* if not allocated, try to read from parent image, if exist */ - if (bs->backing_hd) { - if (!vmdk_is_cid_valid(bs)) -- return -1; -+ return -EINVAL; - ret = bdrv_read(bs->backing_hd, sector_num, buf, n); - if (ret < 0) -- return -1; -+ return ret; - } else { - memset(buf, 0, 512 * n); - } - } else { -- if(bdrv_pread(bs->file, cluster_offset + index_in_cluster * 512, buf, n * 512) != n * 512) -- return -1; -+ ret = bdrv_pread(extent->file, -+ cluster_offset + index_in_cluster * 512, -+ buf, n * 512); -+ if (ret < 0) { -+ return ret; -+ } - } - nb_sectors -= n; - sector_num += n; -@@ -865,7 +1009,7 @@ static int vmdk_write(BlockDriverState * - "(VMDK) Wrong offset: sector_num=0x%" PRIx64 - " total_sectors=0x%" PRIx64 "\n", - sector_num, bs->total_sectors); -- return -1; -+ return -EIO; - } - - while (nb_sectors > 0) { -@@ -888,16 +1032,17 @@ static int vmdk_write(BlockDriverState * - n = nb_sectors; - } - -- if (bdrv_pwrite(bs->file, -+ ret = bdrv_pwrite(extent->file, - cluster_offset + index_in_cluster * 512, -- buf, n * 512) -- != n * 512) { -- return -1; -+ buf, -+ n * 512); -+ if (ret < 0) { -+ return ret; - } - if (m_data.valid) { - /* update L2 tables */ - if (vmdk_L2update(extent, &m_data) == -1) { -- return -1; -+ return -EIO; - } - } - nb_sectors -= n; diff --git a/tools/qemu/patches/0011-VMDK-create-different-subformats.patch b/tools/qemu/patches/0011-VMDK-create-different-subformats.patch deleted file mode 100644 index 7f02772d03..0000000000 --- a/tools/qemu/patches/0011-VMDK-create-different-subformats.patch +++ /dev/null @@ -1,595 +0,0 @@ -From 0d0f2ba577bd05491b5954751787f8b969ca1ec3 Mon Sep 17 00:00:00 2001 -From: Fam Zheng <famcool@gmail.com> -Date: Tue, 19 Jul 2011 08:45:23 +0800 -Subject: [PATCH 11/12] VMDK: create different subformats - -Add create option 'format', with enums: - monolithicSparse - monolithicFlat - twoGbMaxExtentSparse - twoGbMaxExtentFlat -Each creates a subformat image file. The default is monolithicSparse. - -Signed-off-by: Fam Zheng <famcool@gmail.com> -Reviewed-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com> -Signed-off-by: Kevin Wolf <kwolf@redhat.com> ---- - block/vmdk.c | 503 ++++++++++++++++++++++++++++++++--------------------------- - block_int.h | 1 + - 2 files changed, 275 insertions(+), 229 deletions(-) - ---- a/block/vmdk.c -+++ b/block/vmdk.c -@@ -156,8 +156,9 @@ static int vmdk_probe(const uint8_t *buf - #define CHECK_CID 1 - - #define SECTOR_SIZE 512 --#define DESC_SIZE 20*SECTOR_SIZE // 20 sectors of 512 bytes each --#define HEADER_SIZE 512 // first sector of 512 bytes -+#define DESC_SIZE (20 * SECTOR_SIZE) /* 20 sectors of 512 bytes each */ -+#define BUF_SIZE 4096 -+#define HEADER_SIZE 512 /* first sector of 512 bytes */ - - static void vmdk_free_extents(BlockDriverState *bs) - { -@@ -243,168 +244,6 @@ static int vmdk_is_cid_valid(BlockDriver - return 1; - } - --static int vmdk_snapshot_create(const char *filename, const char *backing_file) --{ -- int snp_fd, p_fd; -- int ret; -- uint32_t p_cid; -- char *p_name, *gd_buf, *rgd_buf; -- const char *real_filename, *temp_str; -- VMDK4Header header; -- uint32_t gde_entries, gd_size; -- int64_t gd_offset, rgd_offset, capacity, gt_size; -- char p_desc[DESC_SIZE], s_desc[DESC_SIZE], hdr[HEADER_SIZE]; -- static const char desc_template[] = -- "# Disk DescriptorFile\n" -- "version=1\n" -- "CID=%x\n" -- "parentCID=%x\n" -- "createType=\"monolithicSparse\"\n" -- "parentFileNameHint=\"%s\"\n" -- "\n" -- "# Extent description\n" -- "RW %u SPARSE \"%s\"\n" -- "\n" -- "# The Disk Data Base \n" -- "#DDB\n" -- "\n"; -- -- snp_fd = open(filename, O_RDWR | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE, 0644); -- if (snp_fd < 0) -- return -errno; -- p_fd = open(backing_file, O_RDONLY | O_BINARY | O_LARGEFILE); -- if (p_fd < 0) { -- close(snp_fd); -- return -errno; -- } -- -- /* read the header */ -- if (lseek(p_fd, 0x0, SEEK_SET) == -1) { -- ret = -errno; -- goto fail; -- } -- if (read(p_fd, hdr, HEADER_SIZE) != HEADER_SIZE) { -- ret = -errno; -- goto fail; -- } -- -- /* write the header */ -- if (lseek(snp_fd, 0x0, SEEK_SET) == -1) { -- ret = -errno; -- goto fail; -- } -- if (write(snp_fd, hdr, HEADER_SIZE) == -1) { -- ret = -errno; -- goto fail; -- } -- -- memset(&header, 0, sizeof(header)); -- memcpy(&header,&hdr[4], sizeof(header)); // skip the VMDK4_MAGIC -- -- if (ftruncate(snp_fd, header.grain_offset << 9)) { -- ret = -errno; -- goto fail; -- } -- /* the descriptor offset = 0x200 */ -- if (lseek(p_fd, 0x200, SEEK_SET) == -1) { -- ret = -errno; -- goto fail; -- } -- if (read(p_fd, p_desc, DESC_SIZE) != DESC_SIZE) { -- ret = -errno; -- goto fail; -- } -- -- if ((p_name = strstr(p_desc,"CID")) != NULL) { -- p_name += sizeof("CID"); -- sscanf(p_name,"%x",&p_cid); -- } -- -- real_filename = filename; -- if ((temp_str = strrchr(real_filename, '\\')) != NULL) -- real_filename = temp_str + 1; -- if ((temp_str = strrchr(real_filename, '/')) != NULL) -- real_filename = temp_str + 1; -- if ((temp_str = strrchr(real_filename, ':')) != NULL) -- real_filename = temp_str + 1; -- -- snprintf(s_desc, sizeof(s_desc), desc_template, p_cid, p_cid, backing_file, -- (uint32_t)header.capacity, real_filename); -- -- /* write the descriptor */ -- if (lseek(snp_fd, 0x200, SEEK_SET) == -1) { -- ret = -errno; -- goto fail; -- } -- if (write(snp_fd, s_desc, strlen(s_desc)) == -1) { -- ret = -errno; -- goto fail; -- } -- -- gd_offset = header.gd_offset * SECTOR_SIZE; // offset of GD table -- rgd_offset = header.rgd_offset * SECTOR_SIZE; // offset of RGD table -- capacity = header.capacity * SECTOR_SIZE; // Extent size -- /* -- * Each GDE span 32M disk, means: -- * 512 GTE per GT, each GTE points to grain -- */ -- gt_size = (int64_t)header.num_gtes_per_gte * header.granularity * SECTOR_SIZE; -- if (!gt_size) { -- ret = -EINVAL; -- goto fail; -- } -- gde_entries = (uint32_t)(capacity / gt_size); // number of gde/rgde -- gd_size = gde_entries * sizeof(uint32_t); -- -- /* write RGD */ -- rgd_buf = qemu_malloc(gd_size); -- if (lseek(p_fd, rgd_offset, SEEK_SET) == -1) { -- ret = -errno; -- goto fail_rgd; -- } -- if (read(p_fd, rgd_buf, gd_size) != gd_size) { -- ret = -errno; -- goto fail_rgd; -- } -- if (lseek(snp_fd, rgd_offset, SEEK_SET) == -1) { -- ret = -errno; -- goto fail_rgd; -- } -- if (write(snp_fd, rgd_buf, gd_size) == -1) { -- ret = -errno; -- goto fail_rgd; -- } -- -- /* write GD */ -- gd_buf = qemu_malloc(gd_size); -- if (lseek(p_fd, gd_offset, SEEK_SET) == -1) { -- ret = -errno; -- goto fail_gd; -- } -- if (read(p_fd, gd_buf, gd_size) != gd_size) { -- ret = -errno; -- goto fail_gd; -- } -- if (lseek(snp_fd, gd_offset, SEEK_SET) == -1) { -- ret = -errno; -- goto fail_gd; -- } -- if (write(snp_fd, gd_buf, gd_size) == -1) { -- ret = -errno; -- goto fail_gd; -- } -- ret = 0; -- --fail_gd: -- qemu_free(gd_buf); --fail_rgd: -- qemu_free(rgd_buf); --fail: -- close(p_fd); -- close(snp_fd); -- return ret; --} -- - static int vmdk_parent_open(BlockDriverState *bs) - { - char *p_name; -@@ -1058,68 +897,40 @@ static int vmdk_write(BlockDriverState * - return 0; - } - --static int vmdk_create(const char *filename, QEMUOptionParameter *options) -+ -+static int vmdk_create_extent(const char *filename, int64_t filesize, bool flat) - { -- int fd, i; -+ int ret, i; -+ int fd = 0; - VMDK4Header header; - uint32_t tmp, magic, grains, gd_size, gt_size, gt_count; -- static const char desc_template[] = -- "# Disk DescriptorFile\n" -- "version=1\n" -- "CID=%x\n" -- "parentCID=ffffffff\n" -- "createType=\"monolithicSparse\"\n" -- "\n" -- "# Extent description\n" -- "RW %" PRId64 " SPARSE \"%s\"\n" -- "\n" -- "# The Disk Data Base \n" -- "#DDB\n" -- "\n" -- "ddb.virtualHWVersion = \"%d\"\n" -- "ddb.geometry.cylinders = \"%" PRId64 "\"\n" -- "ddb.geometry.heads = \"16\"\n" -- "ddb.geometry.sectors = \"63\"\n" -- "ddb.adapterType = \"ide\"\n"; -- char desc[1024]; -- const char *real_filename, *temp_str; -- int64_t total_size = 0; -- const char *backing_file = NULL; -- int flags = 0; -- int ret; - -- // Read out options -- while (options && options->name) { -- if (!strcmp(options->name, BLOCK_OPT_SIZE)) { -- total_size = options->value.n / 512; -- } else if (!strcmp(options->name, BLOCK_OPT_BACKING_FILE)) { -- backing_file = options->value.s; -- } else if (!strcmp(options->name, BLOCK_OPT_COMPAT6)) { -- flags |= options->value.n ? BLOCK_FLAG_COMPAT6: 0; -- } -- options++; -+ fd = open( -+ filename, -+ O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE, -+ 0644); -+ if (fd < 0) { -+ return -errno; - } -- -- /* XXX: add support for backing file */ -- if (backing_file) { -- return vmdk_snapshot_create(filename, backing_file); -+ if (flat) { -+ ret = ftruncate(fd, filesize); -+ if (ret < 0) { -+ ret = -errno; -+ } -+ goto exit; - } -- -- fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE, -- 0644); -- if (fd < 0) -- return -errno; - magic = cpu_to_be32(VMDK4_MAGIC); - memset(&header, 0, sizeof(header)); - header.version = 1; - header.flags = 3; /* ?? */ -- header.capacity = total_size; -+ header.capacity = filesize / 512; - header.granularity = 128; - header.num_gtes_per_gte = 512; - -- grains = (total_size + header.granularity - 1) / header.granularity; -+ grains = (filesize / 512 + header.granularity - 1) / header.granularity; - gt_size = ((header.num_gtes_per_gte * sizeof(uint32_t)) + 511) >> 9; -- gt_count = (grains + header.num_gtes_per_gte - 1) / header.num_gtes_per_gte; -+ gt_count = -+ (grains + header.num_gtes_per_gte - 1) / header.num_gtes_per_gte; - gd_size = (gt_count * sizeof(uint32_t) + 511) >> 9; - - header.desc_offset = 1; -@@ -1130,7 +941,6 @@ static int vmdk_create(const char *filen - ((header.gd_offset + gd_size + (gt_size * gt_count) + - header.granularity - 1) / header.granularity) * - header.granularity; -- - /* swap endianness for all header fields */ - header.version = cpu_to_le32(header.version); - header.flags = cpu_to_le32(header.flags); -@@ -1188,27 +998,255 @@ static int vmdk_create(const char *filen - } - } - -- /* compose the descriptor */ -- real_filename = filename; -- if ((temp_str = strrchr(real_filename, '\\')) != NULL) -- real_filename = temp_str + 1; -- if ((temp_str = strrchr(real_filename, '/')) != NULL) -- real_filename = temp_str + 1; -- if ((temp_str = strrchr(real_filename, ':')) != NULL) -- real_filename = temp_str + 1; -- snprintf(desc, sizeof(desc), desc_template, (unsigned int)time(NULL), -- total_size, real_filename, -- (flags & BLOCK_FLAG_COMPAT6 ? 6 : 4), -- total_size / (int64_t)(63 * 16)); -+ ret = 0; -+ exit: -+ close(fd); -+ return ret; -+} - -- /* write the descriptor */ -- lseek(fd, le64_to_cpu(header.desc_offset) << 9, SEEK_SET); -+static int filename_decompose(const char *filename, char *path, char *prefix, -+ char *postfix, size_t buf_len) -+{ -+ const char *p, *q; -+ -+ if (filename == NULL || !strlen(filename)) { -+ fprintf(stderr, "Vmdk: no filename provided.\n"); -+ return -1; -+ } -+ p = strrchr(filename, '/'); -+ if (p == NULL) { -+ p = strrchr(filename, '\\'); -+ } -+ if (p == NULL) { -+ p = strrchr(filename, ':'); -+ } -+ if (p != NULL) { -+ p++; -+ if (p - filename >= buf_len) { -+ return -1; -+ } -+ pstrcpy(path, p - filename + 1, filename); -+ } else { -+ p = filename; -+ path[0] = '\0'; -+ } -+ q = strrchr(p, '.'); -+ if (q == NULL) { -+ pstrcpy(prefix, buf_len, p); -+ postfix[0] = '\0'; -+ } else { -+ if (q - p >= buf_len) { -+ return -1; -+ } -+ pstrcpy(prefix, q - p + 1, p); -+ pstrcpy(postfix, buf_len, q); -+ } -+ return 0; -+} -+ -+static int relative_path(char *dest, int dest_size, -+ const char *base, const char *target) -+{ -+ int i = 0; -+ int n = 0; -+ const char *p, *q; -+#ifdef _WIN32 -+ const char *sep = "\\"; -+#else -+ const char *sep = "/"; -+#endif -+ -+ if (!(dest && base && target)) { -+ return -1; -+ } -+ if (path_is_absolute(target)) { -+ dest[dest_size - 1] = '\0'; -+ strncpy(dest, target, dest_size - 1); -+ return 0; -+ } -+ while (base[i] == target[i]) { -+ i++; -+ } -+ p = &base[i]; -+ q = &target[i]; -+ while (*p) { -+ if (*p == *sep) { -+ n++; -+ } -+ p++; -+ } -+ dest[0] = '\0'; -+ for (; n; n--) { -+ pstrcat(dest, dest_size, ".."); -+ pstrcat(dest, dest_size, sep); -+ } -+ pstrcat(dest, dest_size, q); -+ return 0; -+} -+ -+static int vmdk_create(const char *filename, QEMUOptionParameter *options) -+{ -+ int fd, idx = 0; -+ char desc[BUF_SIZE]; -+ int64_t total_size = 0, filesize; -+ const char *backing_file = NULL; -+ const char *fmt = NULL; -+ int flags = 0; -+ int ret = 0; -+ bool flat, split; -+ char ext_desc_lines[BUF_SIZE] = ""; -+ char path[PATH_MAX], prefix[PATH_MAX], postfix[PATH_MAX]; -+ const int64_t split_size = 0x80000000; /* VMDK has constant split size */ -+ const char *desc_extent_line; -+ char parent_desc_line[BUF_SIZE] = ""; -+ uint32_t parent_cid = 0xffffffff; -+ const char desc_template[] = -+ "# Disk DescriptorFile\n" -+ "version=1\n" -+ "CID=%x\n" -+ "parentCID=%x\n" -+ "createType=\"%s\"\n" -+ "%s" -+ "\n" -+ "# Extent description\n" -+ "%s" -+ "\n" -+ "# The Disk Data Base\n" -+ "#DDB\n" -+ "\n" -+ "ddb.virtualHWVersion = \"%d\"\n" -+ "ddb.geometry.cylinders = \"%" PRId64 "\"\n" -+ "ddb.geometry.heads = \"16\"\n" -+ "ddb.geometry.sectors = \"63\"\n" -+ "ddb.adapterType = \"ide\"\n"; -+ -+ if (filename_decompose(filename, path, prefix, postfix, PATH_MAX)) { -+ return -EINVAL; -+ } -+ /* Read out options */ -+ while (options && options->name) { -+ if (!strcmp(options->name, BLOCK_OPT_SIZE)) { -+ total_size = options->value.n; -+ } else if (!strcmp(options->name, BLOCK_OPT_BACKING_FILE)) { -+ backing_file = options->value.s; -+ } else if (!strcmp(options->name, BLOCK_OPT_COMPAT6)) { -+ flags |= options->value.n ? BLOCK_FLAG_COMPAT6 : 0; -+ } else if (!strcmp(options->name, BLOCK_OPT_SUBFMT)) { -+ fmt = options->value.s; -+ } -+ options++; -+ } -+ if (!fmt) { -+ /* Default format to monolithicSparse */ -+ fmt = "monolithicSparse"; -+ } else if (strcmp(fmt, "monolithicFlat") && -+ strcmp(fmt, "monolithicSparse") && -+ strcmp(fmt, "twoGbMaxExtentSparse") && -+ strcmp(fmt, "twoGbMaxExtentFlat")) { -+ fprintf(stderr, "VMDK: Unknown subformat: %s\n", fmt); -+ return -EINVAL; -+ } -+ split = !(strcmp(fmt, "twoGbMaxExtentFlat") && -+ strcmp(fmt, "twoGbMaxExtentSparse")); -+ flat = !(strcmp(fmt, "monolithicFlat") && -+ strcmp(fmt, "twoGbMaxExtentFlat")); -+ if (flat) { -+ desc_extent_line = "RW %lld FLAT \"%s\" 0\n"; -+ } else { -+ desc_extent_line = "RW %lld SPARSE \"%s\"\n"; -+ } -+ if (flat && backing_file) { -+ /* not supporting backing file for flat image */ -+ return -ENOTSUP; -+ } -+ if (backing_file) { -+ char parent_filename[PATH_MAX]; -+ BlockDriverState *bs = bdrv_new(""); -+ ret = bdrv_open(bs, backing_file, 0, NULL); -+ if (ret != 0) { -+ bdrv_delete(bs); -+ return ret; -+ } -+ if (strcmp(bs->drv->format_name, "vmdk")) { -+ bdrv_delete(bs); -+ return -EINVAL; -+ } -+ filesize = bdrv_getlength(bs); -+ parent_cid = vmdk_read_cid(bs, 0); -+ bdrv_delete(bs); -+ relative_path(parent_filename, sizeof(parent_filename), -+ filename, backing_file); -+ snprintf(parent_desc_line, sizeof(parent_desc_line), -+ "parentFileNameHint=\"%s\"", parent_filename); -+ } -+ -+ /* Create extents */ -+ filesize = total_size; -+ while (filesize > 0) { -+ char desc_line[BUF_SIZE]; -+ char ext_filename[PATH_MAX]; -+ char desc_filename[PATH_MAX]; -+ int64_t size = filesize; -+ -+ if (split && size > split_size) { -+ size = split_size; -+ } -+ if (split) { -+ snprintf(desc_filename, sizeof(desc_filename), "%s-%c%03d%s", -+ prefix, flat ? 'f' : 's', ++idx, postfix); -+ } else if (flat) { -+ snprintf(desc_filename, sizeof(desc_filename), "%s-flat%s", -+ prefix, postfix); -+ } else { -+ snprintf(desc_filename, sizeof(desc_filename), "%s%s", -+ prefix, postfix); -+ } -+ snprintf(ext_filename, sizeof(ext_filename), "%s%s", -+ path, desc_filename); -+ -+ if (vmdk_create_extent(ext_filename, size, flat)) { -+ return -EINVAL; -+ } -+ filesize -= size; -+ -+ /* Format description line */ -+ snprintf(desc_line, sizeof(desc_line), -+ desc_extent_line, size / 512, desc_filename); -+ pstrcat(ext_desc_lines, sizeof(ext_desc_lines), desc_line); -+ } -+ /* generate descriptor file */ -+ snprintf(desc, sizeof(desc), desc_template, -+ (unsigned int)time(NULL), -+ parent_cid, -+ fmt, -+ parent_desc_line, -+ ext_desc_lines, -+ (flags & BLOCK_FLAG_COMPAT6 ? 6 : 4), -+ total_size / (int64_t)(63 * 16 * 512)); -+ if (split || flat) { -+ fd = open( -+ filename, -+ O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE, -+ 0644); -+ } else { -+ fd = open( -+ filename, -+ O_WRONLY | O_BINARY | O_LARGEFILE, -+ 0644); -+ } -+ if (fd < 0) { -+ return -errno; -+ } -+ /* the descriptor offset = 0x200 */ -+ if (!split && !flat && 0x200 != lseek(fd, 0x200, SEEK_SET)) { -+ ret = -errno; -+ goto exit; -+ } - ret = qemu_write_full(fd, desc, strlen(desc)); - if (ret != strlen(desc)) { - ret = -errno; - goto exit; - } -- - ret = 0; - exit: - close(fd); -@@ -1252,6 +1290,13 @@ static QEMUOptionParameter vmdk_create_o - .type = OPT_FLAG, - .help = "VMDK version 6 image" - }, -+ { -+ .name = BLOCK_OPT_SUBFMT, -+ .type = OPT_STRING, -+ .help = -+ "VMDK flat extent format, can be one of " -+ "{monolithicSparse (default) | monolithicFlat | twoGbMaxExtentSparse | twoGbMaxExtentFlat} " -+ }, - { NULL } - }; - ---- a/block_int.h -+++ b/block_int.h -@@ -39,6 +39,7 @@ - #define BLOCK_OPT_CLUSTER_SIZE "cluster_size" - #define BLOCK_OPT_TABLE_SIZE "table_size" - #define BLOCK_OPT_PREALLOC "preallocation" -+#define BLOCK_OPT_SUBFMT "subformat" - - typedef struct AIOPool { - void (*cancel)(BlockDriverAIOCB *acb); diff --git a/tools/qemu/patches/0012-vmdk-Allow-selecting-SCSI-adapter-in-image-creation.patch b/tools/qemu/patches/0012-vmdk-Allow-selecting-SCSI-adapter-in-image-creation.patch deleted file mode 100644 index fc3dee361e..0000000000 --- a/tools/qemu/patches/0012-vmdk-Allow-selecting-SCSI-adapter-in-image-creation.patch +++ /dev/null @@ -1,114 +0,0 @@ -From 5483df4df2729a5d1e4888a48039b1cd90438480 Mon Sep 17 00:00:00 2001 -From: Othmar Pasteka <pasteka@kabsi.at> -Date: Wed, 30 Jan 2013 00:26:52 +0100 -Subject: [PATCH 12/12] vmdk: Allow selecting SCSI adapter in image creation - -Introduce a new option "adapter_type" when converting to vmdk images. -It can be one of the following: ide (default), buslogic, lsilogic -or legacyESX (according to the vmdk spec from vmware). - -In case of a non-ide adapter, heads is set to 255 instead of the 16. -The latter is used for "ide". - -Also see LP#545089 - -Signed-off-by: Othmar Pasteka <pasteka@kabsi.at> -Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> ---- - block/vmdk.c | 31 ++++++++++++++++++++++++++++--- - block_int.h | 1 + - 2 files changed, 29 insertions(+), 3 deletions(-) - ---- a/block/vmdk.c -+++ b/block/vmdk.c -@@ -1089,6 +1089,7 @@ static int vmdk_create(const char *filen - int fd, idx = 0; - char desc[BUF_SIZE]; - int64_t total_size = 0, filesize; -+ const char *adapter_type = NULL; - const char *backing_file = NULL; - const char *fmt = NULL; - int flags = 0; -@@ -1100,6 +1101,7 @@ static int vmdk_create(const char *filen - const char *desc_extent_line; - char parent_desc_line[BUF_SIZE] = ""; - uint32_t parent_cid = 0xffffffff; -+ uint32_t number_heads = 16; - const char desc_template[] = - "# Disk DescriptorFile\n" - "version=1\n" -@@ -1116,9 +1118,9 @@ static int vmdk_create(const char *filen - "\n" - "ddb.virtualHWVersion = \"%d\"\n" - "ddb.geometry.cylinders = \"%" PRId64 "\"\n" -- "ddb.geometry.heads = \"16\"\n" -+ "ddb.geometry.heads = \"%d\"\n" - "ddb.geometry.sectors = \"63\"\n" -- "ddb.adapterType = \"ide\"\n"; -+ "ddb.adapterType = \"%s\"\n"; - - if (filename_decompose(filename, path, prefix, postfix, PATH_MAX)) { - return -EINVAL; -@@ -1127,6 +1129,8 @@ static int vmdk_create(const char *filen - while (options && options->name) { - if (!strcmp(options->name, BLOCK_OPT_SIZE)) { - total_size = options->value.n; -+ } else if (!strcmp(options->name, BLOCK_OPT_ADAPTER_TYPE)) { -+ adapter_type = options->value.s; - } else if (!strcmp(options->name, BLOCK_OPT_BACKING_FILE)) { - backing_file = options->value.s; - } else if (!strcmp(options->name, BLOCK_OPT_COMPAT6)) { -@@ -1136,6 +1140,20 @@ static int vmdk_create(const char *filen - } - options++; - } -+ if (!adapter_type) { -+ adapter_type = "ide"; -+ } else if (strcmp(adapter_type, "ide") && -+ strcmp(adapter_type, "buslogic") && -+ strcmp(adapter_type, "lsilogic") && -+ strcmp(adapter_type, "legacyESX")) { -+ fprintf(stderr, "VMDK: Unknown adapter type: '%s'.\n", adapter_type); -+ return -EINVAL; -+ } -+ if (strcmp(adapter_type, "ide") != 0) { -+ /* that's the number of heads with which vmware operates when -+ creating, exporting, etc. vmdk files with a non-ide adapter type */ -+ number_heads = 255; -+ } - if (!fmt) { - /* Default format to monolithicSparse */ - fmt = "monolithicSparse"; -@@ -1222,7 +1240,8 @@ static int vmdk_create(const char *filen - parent_desc_line, - ext_desc_lines, - (flags & BLOCK_FLAG_COMPAT6 ? 6 : 4), -- total_size / (int64_t)(63 * 16 * 512)); -+ total_size / (int64_t)(63 * number_heads * 512), number_heads, -+ adapter_type); - if (split || flat) { - fd = open( - filename, -@@ -1281,6 +1300,12 @@ static QEMUOptionParameter vmdk_create_o - .help = "Virtual disk size" - }, - { -+ .name = BLOCK_OPT_ADAPTER_TYPE, -+ .type = OPT_STRING, -+ .help = "Virtual adapter type, can be one of " -+ "ide (default), lsilogic, buslogic or legacyESX" -+ }, -+ { - .name = BLOCK_OPT_BACKING_FILE, - .type = OPT_STRING, - .help = "File name of a base image" ---- a/block_int.h -+++ b/block_int.h -@@ -40,6 +40,7 @@ - #define BLOCK_OPT_TABLE_SIZE "table_size" - #define BLOCK_OPT_PREALLOC "preallocation" - #define BLOCK_OPT_SUBFMT "subformat" -+#define BLOCK_OPT_ADAPTER_TYPE "adapter_type" - - typedef struct AIOPool { - void (*cancel)(BlockDriverAIOCB *acb); |