* [Qemu-devel] [PATCH 11/12] VMDK: vmdk_create and options for mono flat image
@ 2011-06-04 0:44 Fam Zheng
2011-06-18 18:19 ` Stefan Hajnoczi
0 siblings, 1 reply; 2+ messages in thread
From: Fam Zheng @ 2011-06-04 0:44 UTC (permalink / raw)
To: qemu-devel; +Cc: Kevin Wolf, Stefan Hajnoczi, Christoph Hellwig
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 <famcool@gmail.com>
---
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);
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [Qemu-devel] [PATCH 11/12] VMDK: vmdk_create and options for mono flat image
2011-06-04 0:44 [Qemu-devel] [PATCH 11/12] VMDK: vmdk_create and options for mono flat image Fam Zheng
@ 2011-06-18 18:19 ` Stefan Hajnoczi
0 siblings, 0 replies; 2+ messages in thread
From: Stefan Hajnoczi @ 2011-06-18 18:19 UTC (permalink / raw)
To: Fam Zheng; +Cc: Kevin Wolf, qemu-devel, Christoph Hellwig
On Sat, Jun 4, 2011 at 1:44 AM, Fam Zheng <famcool@gmail.com> wrote:
> + if (flat) {
The flat and !flat cases are too big, please split them out into functions.
> + 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";
This is almost identical to the desc_template[] below. Please use
createType=%s and extent type format specifiers to share this template
instead of copy-pasting it.
> + 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 */
Is this comment still true? It seems there is support for a backing
file via vmdk_snapshot_create().
Stefan
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2011-06-18 18:20 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-06-04 0:44 [Qemu-devel] [PATCH 11/12] VMDK: vmdk_create and options for mono flat image Fam Zheng
2011-06-18 18:19 ` Stefan Hajnoczi
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.