Skip to content

Commit

Permalink
vmdk: Fix creating big description file
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: Stefan Hajnoczi <[email protected]>
(cherry picked from commit af057fe)

Conflicts:

	block/vmdk.c
	tests/qemu-iotests/059
	tests/qemu-iotests/059.out

*removed dependencies on 4823970 and 4f6fd34

Signed-off-by: Michael Roth <[email protected]>
  • Loading branch information
Fam Zheng authored and mdroth committed Dec 9, 2013
1 parent 982c8c5 commit 12f7410
Show file tree
Hide file tree
Showing 3 changed files with 2,060 additions and 31 deletions.
59 changes: 36 additions & 23 deletions block/vmdk.c
Original file line number Diff line number Diff line change
Expand Up @@ -1538,15 +1538,15 @@ static int filename_decompose(const char *filename, char *path, char *prefix,
static int vmdk_create(const char *filename, QEMUOptionParameter *options)
{
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;
const char *fmt = NULL;
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;
Expand Down Expand Up @@ -1574,8 +1574,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)) {
return -EINVAL;
ret = -EINVAL;
goto exit;
}
/* Read out options */
while (options && options->name) {
Expand All @@ -1601,7 +1604,8 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options)
strcmp(adapter_type, "lsilogic") &&
strcmp(adapter_type, "legacyESX")) {
fprintf(stderr, "VMDK: Unknown adapter type: '%s'.\n", 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
Expand All @@ -1617,7 +1621,8 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options)
strcmp(fmt, "twoGbMaxExtentFlat") &&
strcmp(fmt, "streamOptimized")) {
fprintf(stderr, "VMDK: Unknown subformat: %s\n", fmt);
return -EINVAL;
ret = -EINVAL;
goto exit;
}
split = !(strcmp(fmt, "twoGbMaxExtentFlat") &&
strcmp(fmt, "twoGbMaxExtentSparse"));
Expand All @@ -1631,18 +1636,20 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options)
}
if (flat && backing_file) {
/* not supporting backing file for flat image */
return -ENOTSUP;
ret = -ENOTSUP;
goto exit;
}
if (backing_file) {
BlockDriverState *bs = bdrv_new("");
ret = bdrv_open(bs, backing_file, NULL, 0, NULL);
if (ret != 0) {
bdrv_delete(bs);
return ret;
goto exit;
}
if (strcmp(bs->drv->format_name, "vmdk")) {
bdrv_delete(bs);
return -EINVAL;
ret = -EINVAL;
goto exit;
}
parent_cid = vmdk_read_cid(bs, 0);
bdrv_delete(bs);
Expand Down Expand Up @@ -1676,25 +1683,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,
Expand All @@ -1705,21 +1714,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;
}

Expand Down
5 changes: 5 additions & 0 deletions tests/qemu-iotests/059
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,11 @@ poke_file "$TEST_IMG" "$capacity_offset" "\xff\xff\xff\xff"
poke_file "$TEST_IMG" "$grain_table_size_offset" "\x01\x00\x00\x00"
{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir

echo
echo "=== Testing big twoGbMaxExtentFlat ==="
IMGOPTS="subformat=twoGbMaxExtentFlat" _make_test_img 1000G
$QEMU_IMG info $TEST_IMG | _filter_testdir | sed -e 's/cid: [0-9]*/cid: XXXXXXXX/'

# success, all done
echo "*** done"
rm -f $seq.full
Expand Down
Loading

0 comments on commit 12f7410

Please sign in to comment.