qemu-devel
[Top][All Lists]
Advanced

[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);



reply via email to

[Prev in Thread] Current Thread [Next in Thread]