[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 11/12] VMDK: vmdk_create and options for mono flat i
From: |
Fam Zheng |
Subject: |
[Qemu-devel] [PATCH 11/12] VMDK: vmdk_create and options for mono flat image |
Date: |
Sat, 4 Jun 2011 08:44:08 +0800 |
A flag is added, as there are basically two extent type: SPARSE and
FLAT, this flat can be used in future subformats too.
Create vmdk mono flat image with `qemu-img create -o flat`.
Signed-off-by: Fam Zheng <address@hidden>
---
block/vmdk.c | 297 ++++++++++++++++++++++++++++++++++++----------------------
block_int.h | 1 +
2 files changed, 185 insertions(+), 113 deletions(-)
diff --git a/block/vmdk.c b/block/vmdk.c
index 85e868e..43b47e2 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -835,7 +835,7 @@ static int vmdk_is_allocated(BlockDriverState *bs,
int64_t sector_num,
ret = get_cluster_offset(bs, extent, NULL, sector_num << 9,
0, &offset);
if (ret) {
return 0;
- }
+ }
index_in_cluster = sector_num % extent->cluster_sectors;
n = extent->cluster_sectors - index_in_cluster;
}
@@ -957,32 +957,16 @@ static int vmdk_write(BlockDriverState *bs,
int64_t sector_num,
static int vmdk_create(const char *filename, QEMUOptionParameter *options)
{
- int fd, i;
+ int fd;
+ int64_t i;
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;
+ bool flat = false;
int ret;
// Read out options
@@ -993,114 +977,196 @@ static int vmdk_create(const char *filename,
QEMUOptionParameter *options)
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_FLAT)) {
+ flat = options->value.n;
}
options++;
}
- /* XXX: add support for backing file */
- if (backing_file) {
- return vmdk_snapshot_create(filename, backing_file);
- }
-
- 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 = 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);
-
- grains = (total_size + 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;
- gd_size = (gt_count * sizeof(uint32_t) + 511) >> 9;
-
- header.desc_offset = 1;
- header.desc_size = 20;
- header.rgd_offset = header.desc_offset + header.desc_size;
- header.gd_offset = header.rgd_offset + gd_size + (gt_size * gt_count);
- header.grain_offset =
- ((header.gd_offset + gd_size + (gt_size * gt_count) +
- header.granularity - 1) / header.granularity) *
- header.granularity;
-
- 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);
- header.gd_offset = cpu_to_le64(header.gd_offset);
- header.grain_offset = cpu_to_le64(header.grain_offset);
-
- header.check_bytes[0] = 0xa;
- header.check_bytes[1] = 0x20;
- header.check_bytes[2] = 0xd;
- header.check_bytes[3] = 0xa;
-
- /* write all the data */
- ret = qemu_write_full(fd, &magic, sizeof(magic));
- if (ret != sizeof(magic)) {
- ret = -errno;
- goto exit;
- }
- ret = qemu_write_full(fd, &header, sizeof(header));
- if (ret != sizeof(header)) {
- ret = -errno;
- goto exit;
- }
-
- ret = ftruncate(fd, header.grain_offset << 9);
- if (ret < 0) {
- ret = -errno;
- goto exit;
- }
+ if (flat) {
+ const char desc_template[] =
+ "# Disk DescriptorFile\n"
+ "version=1\n"
+ "CID=%x\n"
+ "parentCID=ffffffff\n"
+ "createType=\"monolithicFlat\"\n"
+ "\n"
+ "# Extent description\n"
+ "RW %" PRId64 " FLAT \"%s\" 0\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 ext_filename[1024];
+ strncpy(ext_filename, filename, 1024);
+ ext_filename[1023] = '\0';
+ if (backing_file) {
+ /* not supporting backing file for flat image */
+ return -1;
+ }
+ if (!strcmp(&ext_filename[strlen(ext_filename) - 5], ".vmdk"))
+ strcpy(&ext_filename[strlen(ext_filename) - 5], "-flat.vmdk");
+ else
+ strcat(ext_filename, "-flat.vmdk");
+ /* create extent first */
+ fd = open(
+ ext_filename,
+ O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE,
+ 0644);
+ if (fd < 0)
+ return -errno;
+ ret = ftruncate(fd, total_size * 512);
+ if (ret) goto exit;
+ close(fd);
+
+ /* generate descriptor file */
+ snprintf(desc, sizeof(desc), desc_template, (unsigned int)time(NULL),
+ total_size, ext_filename,
+ (flags & BLOCK_FLAG_COMPAT6 ? 6 : 4),
+ total_size / (int64_t)(63 * 16));
+ fd = open(
+ filename,
+ O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE,
+ 0644);
+ if (fd < 0)
+ return -errno;
+ ret = qemu_write_full(fd, desc, strlen(desc));
+ if (ret != strlen(desc)) {
+ ret = -errno;
+ goto exit;
+ }
+ ret = 0;
+ } else {
+ 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";
+ /* XXX: add support for backing file */
+ if (backing_file) {
+ return vmdk_snapshot_create(filename, backing_file);
+ }
- /* write grain directory */
- lseek(fd, le64_to_cpu(header.rgd_offset) << 9, SEEK_SET);
- for (i = 0, tmp = header.rgd_offset + gd_size;
- i < gt_count; i++, tmp += gt_size) {
- ret = qemu_write_full(fd, &tmp, sizeof(tmp));
- if (ret != sizeof(tmp)) {
+ 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 = 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);
+
+ grains = (total_size + 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;
+ gd_size = (gt_count * sizeof(uint32_t) + 511) >> 9;
+
+ header.desc_offset = 1;
+ header.desc_size = 20;
+ header.rgd_offset = header.desc_offset + header.desc_size;
+ header.gd_offset = header.rgd_offset + gd_size + (gt_size * gt_count);
+ header.grain_offset =
+ ((header.gd_offset + gd_size + (gt_size * gt_count) +
+ header.granularity - 1) / header.granularity) *
+ header.granularity;
+
+ 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);
+ header.gd_offset = cpu_to_le64(header.gd_offset);
+ header.grain_offset = cpu_to_le64(header.grain_offset);
+
+ header.check_bytes[0] = 0xa;
+ header.check_bytes[1] = 0x20;
+ header.check_bytes[2] = 0xd;
+ header.check_bytes[3] = 0xa;
+
+ /* write all the data */
+ ret = qemu_write_full(fd, &magic, sizeof(magic));
+ if (ret != sizeof(magic)) {
+ ret = -errno;
+ goto exit;
+ }
+ ret = qemu_write_full(fd, &header, sizeof(header));
+ if (ret != sizeof(header)) {
ret = -errno;
goto exit;
}
- }
- /* write backup grain directory */
- lseek(fd, le64_to_cpu(header.gd_offset) << 9, SEEK_SET);
- for (i = 0, tmp = header.gd_offset + gd_size;
- i < gt_count; i++, tmp += gt_size) {
- ret = qemu_write_full(fd, &tmp, sizeof(tmp));
- if (ret != sizeof(tmp)) {
+ ret = ftruncate(fd, header.grain_offset << 9);
+ if (ret < 0) {
ret = -errno;
goto exit;
}
- }
- /* 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));
+ /* write grain directory */
+ lseek(fd, le64_to_cpu(header.rgd_offset) << 9, SEEK_SET);
+ for (i = 0, tmp = header.rgd_offset + gd_size;
+ i < gt_count; i++, tmp += gt_size) {
+ ret = qemu_write_full(fd, &tmp, sizeof(tmp));
+ if (ret != sizeof(tmp)) {
+ ret = -errno;
+ goto exit;
+ }
+ }
- /* write the descriptor */
- lseek(fd, le64_to_cpu(header.desc_offset) << 9, SEEK_SET);
- ret = qemu_write_full(fd, desc, strlen(desc));
- if (ret != strlen(desc)) {
- ret = -errno;
- goto exit;
- }
+ /* write backup grain directory */
+ lseek(fd, le64_to_cpu(header.gd_offset) << 9, SEEK_SET);
+ for (i = 0, tmp = header.gd_offset + gd_size;
+ i < gt_count; i++, tmp += gt_size) {
+ ret = qemu_write_full(fd, &tmp, sizeof(tmp));
+ if (ret != sizeof(tmp)) {
+ ret = -errno;
+ goto exit;
+ }
+ }
- ret = 0;
+ /* 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));
+
+ /* write the descriptor */
+ lseek(fd, le64_to_cpu(header.desc_offset) << 9, SEEK_SET);
+ ret = qemu_write_full(fd, desc, strlen(desc));
+ if (ret != strlen(desc)) {
+ ret = -errno;
+ goto exit;
+ }
+ ret = 0;
+ }
exit:
close(fd);
return ret;
@@ -1148,6 +1214,11 @@ static QEMUOptionParameter vmdk_create_options[] = {
.type = OPT_FLAG,
.help = "VMDK version 6 image"
},
+ {
+ .name = BLOCK_OPT_FLAT,
+ .type = OPT_FLAG,
+ .help = "VMDK flat extent image"
+ },
{ NULL }
};
diff --git a/block_int.h b/block_int.h
index fa91337..dd8f8cb 100644
--- 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_FLAT "flat"
typedef struct AIOPool {
void (*cancel)(BlockDriverAIOCB *acb);
- [Qemu-devel] [PATCH 11/12] VMDK: vmdk_create and options for mono flat image,
Fam Zheng <=