aboutsummaryrefslogtreecommitdiff
path: root/block/vmdk.c
diff options
context:
space:
mode:
authorFam Zheng <famz@redhat.com>2013-12-03 10:41:05 +0800
committerStefan Hajnoczi <stefanha@redhat.com>2013-12-03 09:54:16 +0100
commitaf057fe74092df2e7a576448ddbdc0daac1370bf (patch)
tree10b4db9029cdb6a5678b43693ff9431876832cbc /block/vmdk.c
parent7b6b145dbc62162df818dc2c5153defd0417c688 (diff)
vmdk: Fix creating big description file
The buffer for description file was 4096 which only covers a few hundred of extents. This changes the buffer to dynamic allocated with g_strdup_printf in order to support bigger cases. Signed-off-by: Fam Zheng <famz@redhat.com> Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Diffstat (limited to 'block/vmdk.c')
-rw-r--r--block/vmdk.c62
1 files changed, 38 insertions, 24 deletions
diff --git a/block/vmdk.c b/block/vmdk.c
index 88d09e3e16..eb84f46a7b 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -1596,7 +1596,7 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
Error **errp)
{
int fd, idx = 0;
- char desc[BUF_SIZE];
+ char *desc = NULL;
int64_t total_size = 0, filesize;
const char *adapter_type = NULL;
const char *backing_file = NULL;
@@ -1604,7 +1604,7 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
int flags = 0;
int ret = 0;
bool flat, split, compress;
- char ext_desc_lines[BUF_SIZE] = "";
+ GString *ext_desc_lines;
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;
@@ -1632,8 +1632,11 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
"ddb.geometry.sectors = \"63\"\n"
"ddb.adapterType = \"%s\"\n";
+ ext_desc_lines = g_string_new(NULL);
+
if (filename_decompose(filename, path, prefix, postfix, PATH_MAX, errp)) {
- return -EINVAL;
+ ret = -EINVAL;
+ goto exit;
}
/* Read out options */
while (options && options->name) {
@@ -1659,7 +1662,8 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
strcmp(adapter_type, "lsilogic") &&
strcmp(adapter_type, "legacyESX")) {
error_setg(errp, "Unknown adapter type: '%s'", adapter_type);
- return -EINVAL;
+ ret = -EINVAL;
+ goto exit;
}
if (strcmp(adapter_type, "ide") != 0) {
/* that's the number of heads with which vmware operates when
@@ -1675,7 +1679,8 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
strcmp(fmt, "twoGbMaxExtentFlat") &&
strcmp(fmt, "streamOptimized")) {
error_setg(errp, "Unknown subformat: '%s'", fmt);
- return -EINVAL;
+ ret = -EINVAL;
+ goto exit;
}
split = !(strcmp(fmt, "twoGbMaxExtentFlat") &&
strcmp(fmt, "twoGbMaxExtentSparse"));
@@ -1689,22 +1694,25 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
}
if (flat && backing_file) {
error_setg(errp, "Flat image can't have backing file");
- return -ENOTSUP;
+ ret = -ENOTSUP;
+ goto exit;
}
if (flat && zeroed_grain) {
error_setg(errp, "Flat image can't enable zeroed grain");
- return -ENOTSUP;
+ ret = -ENOTSUP;
+ goto exit;
}
if (backing_file) {
BlockDriverState *bs = bdrv_new("");
ret = bdrv_open(bs, backing_file, NULL, BDRV_O_NO_BACKING, NULL, errp);
if (ret != 0) {
bdrv_unref(bs);
- return ret;
+ goto exit;
}
if (strcmp(bs->drv->format_name, "vmdk")) {
bdrv_unref(bs);
- return -EINVAL;
+ ret = -EINVAL;
+ goto exit;
}
parent_cid = vmdk_read_cid(bs, 0);
bdrv_unref(bs);
@@ -1738,25 +1746,27 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
if (vmdk_create_extent(ext_filename, size,
flat, compress, zeroed_grain)) {
- return -EINVAL;
+ ret = -EINVAL;
+ goto exit;
}
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);
+ g_string_append(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 * number_heads * 512), number_heads,
- adapter_type);
+ desc = g_strdup_printf(desc_template,
+ (unsigned int)time(NULL),
+ parent_cid,
+ fmt,
+ parent_desc_line,
+ ext_desc_lines->str,
+ (flags & BLOCK_FLAG_COMPAT6 ? 6 : 4),
+ total_size / (int64_t)(63 * number_heads * 512),
+ number_heads,
+ adapter_type);
if (split || flat) {
fd = qemu_open(filename,
O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE,
@@ -1767,21 +1777,25 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
0644);
}
if (fd < 0) {
- return -errno;
+ ret = -errno;
+ goto exit;
}
/* the descriptor offset = 0x200 */
if (!split && !flat && 0x200 != lseek(fd, 0x200, SEEK_SET)) {
ret = -errno;
- goto exit;
+ goto close_exit;
}
ret = qemu_write_full(fd, desc, strlen(desc));
if (ret != strlen(desc)) {
ret = -errno;
- goto exit;
+ goto close_exit;
}
ret = 0;
-exit:
+close_exit:
qemu_close(fd);
+exit:
+ g_free(desc);
+ g_string_free(ext_desc_lines, true);
return ret;
}