diff options
Diffstat (limited to 'tools/qemu/patches/0011-VMDK-create-different-subformats.patch')
-rw-r--r-- | tools/qemu/patches/0011-VMDK-create-different-subformats.patch | 595 |
1 files changed, 0 insertions, 595 deletions
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); |