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>
This commit is contained in:
		
							parent
							
								
									7b6b145dbc
								
							
						
					
					
						commit
						af057fe740
					
				
							
								
								
									
										62
									
								
								block/vmdk.c
									
									
									
									
									
								
							
							
						
						
									
										62
									
								
								block/vmdk.c
									
									
									
									
									
								
							@ -1596,7 +1596,7 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
 | 
				
			|||||||
                       Error **errp)
 | 
					                       Error **errp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    int fd, idx = 0;
 | 
					    int fd, idx = 0;
 | 
				
			||||||
    char desc[BUF_SIZE];
 | 
					    char *desc = NULL;
 | 
				
			||||||
    int64_t total_size = 0, filesize;
 | 
					    int64_t total_size = 0, filesize;
 | 
				
			||||||
    const char *adapter_type = NULL;
 | 
					    const char *adapter_type = NULL;
 | 
				
			||||||
    const char *backing_file = NULL;
 | 
					    const char *backing_file = NULL;
 | 
				
			||||||
@ -1604,7 +1604,7 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
 | 
				
			|||||||
    int flags = 0;
 | 
					    int flags = 0;
 | 
				
			||||||
    int ret = 0;
 | 
					    int ret = 0;
 | 
				
			||||||
    bool flat, split, compress;
 | 
					    bool flat, split, compress;
 | 
				
			||||||
    char ext_desc_lines[BUF_SIZE] = "";
 | 
					    GString *ext_desc_lines;
 | 
				
			||||||
    char path[PATH_MAX], prefix[PATH_MAX], postfix[PATH_MAX];
 | 
					    char path[PATH_MAX], prefix[PATH_MAX], postfix[PATH_MAX];
 | 
				
			||||||
    const int64_t split_size = 0x80000000;  /* VMDK has constant split size */
 | 
					    const int64_t split_size = 0x80000000;  /* VMDK has constant split size */
 | 
				
			||||||
    const char *desc_extent_line;
 | 
					    const char *desc_extent_line;
 | 
				
			||||||
@ -1632,8 +1632,11 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
 | 
				
			|||||||
        "ddb.geometry.sectors = \"63\"\n"
 | 
					        "ddb.geometry.sectors = \"63\"\n"
 | 
				
			||||||
        "ddb.adapterType = \"%s\"\n";
 | 
					        "ddb.adapterType = \"%s\"\n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ext_desc_lines = g_string_new(NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (filename_decompose(filename, path, prefix, postfix, PATH_MAX, errp)) {
 | 
					    if (filename_decompose(filename, path, prefix, postfix, PATH_MAX, errp)) {
 | 
				
			||||||
        return -EINVAL;
 | 
					        ret = -EINVAL;
 | 
				
			||||||
 | 
					        goto exit;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    /* Read out options */
 | 
					    /* Read out options */
 | 
				
			||||||
    while (options && options->name) {
 | 
					    while (options && options->name) {
 | 
				
			||||||
@ -1659,7 +1662,8 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
 | 
				
			|||||||
               strcmp(adapter_type, "lsilogic") &&
 | 
					               strcmp(adapter_type, "lsilogic") &&
 | 
				
			||||||
               strcmp(adapter_type, "legacyESX")) {
 | 
					               strcmp(adapter_type, "legacyESX")) {
 | 
				
			||||||
        error_setg(errp, "Unknown adapter type: '%s'", adapter_type);
 | 
					        error_setg(errp, "Unknown adapter type: '%s'", adapter_type);
 | 
				
			||||||
        return -EINVAL;
 | 
					        ret = -EINVAL;
 | 
				
			||||||
 | 
					        goto exit;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (strcmp(adapter_type, "ide") != 0) {
 | 
					    if (strcmp(adapter_type, "ide") != 0) {
 | 
				
			||||||
        /* that's the number of heads with which vmware operates when
 | 
					        /* 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, "twoGbMaxExtentFlat") &&
 | 
				
			||||||
               strcmp(fmt, "streamOptimized")) {
 | 
					               strcmp(fmt, "streamOptimized")) {
 | 
				
			||||||
        error_setg(errp, "Unknown subformat: '%s'", fmt);
 | 
					        error_setg(errp, "Unknown subformat: '%s'", fmt);
 | 
				
			||||||
        return -EINVAL;
 | 
					        ret = -EINVAL;
 | 
				
			||||||
 | 
					        goto exit;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    split = !(strcmp(fmt, "twoGbMaxExtentFlat") &&
 | 
					    split = !(strcmp(fmt, "twoGbMaxExtentFlat") &&
 | 
				
			||||||
              strcmp(fmt, "twoGbMaxExtentSparse"));
 | 
					              strcmp(fmt, "twoGbMaxExtentSparse"));
 | 
				
			||||||
@ -1689,22 +1694,25 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    if (flat && backing_file) {
 | 
					    if (flat && backing_file) {
 | 
				
			||||||
        error_setg(errp, "Flat image can't have backing file");
 | 
					        error_setg(errp, "Flat image can't have backing file");
 | 
				
			||||||
        return -ENOTSUP;
 | 
					        ret = -ENOTSUP;
 | 
				
			||||||
 | 
					        goto exit;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (flat && zeroed_grain) {
 | 
					    if (flat && zeroed_grain) {
 | 
				
			||||||
        error_setg(errp, "Flat image can't enable zeroed grain");
 | 
					        error_setg(errp, "Flat image can't enable zeroed grain");
 | 
				
			||||||
        return -ENOTSUP;
 | 
					        ret = -ENOTSUP;
 | 
				
			||||||
 | 
					        goto exit;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (backing_file) {
 | 
					    if (backing_file) {
 | 
				
			||||||
        BlockDriverState *bs = bdrv_new("");
 | 
					        BlockDriverState *bs = bdrv_new("");
 | 
				
			||||||
        ret = bdrv_open(bs, backing_file, NULL, BDRV_O_NO_BACKING, NULL, errp);
 | 
					        ret = bdrv_open(bs, backing_file, NULL, BDRV_O_NO_BACKING, NULL, errp);
 | 
				
			||||||
        if (ret != 0) {
 | 
					        if (ret != 0) {
 | 
				
			||||||
            bdrv_unref(bs);
 | 
					            bdrv_unref(bs);
 | 
				
			||||||
            return ret;
 | 
					            goto exit;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if (strcmp(bs->drv->format_name, "vmdk")) {
 | 
					        if (strcmp(bs->drv->format_name, "vmdk")) {
 | 
				
			||||||
            bdrv_unref(bs);
 | 
					            bdrv_unref(bs);
 | 
				
			||||||
            return -EINVAL;
 | 
					            ret = -EINVAL;
 | 
				
			||||||
 | 
					            goto exit;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        parent_cid = vmdk_read_cid(bs, 0);
 | 
					        parent_cid = vmdk_read_cid(bs, 0);
 | 
				
			||||||
        bdrv_unref(bs);
 | 
					        bdrv_unref(bs);
 | 
				
			||||||
@ -1738,25 +1746,27 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        if (vmdk_create_extent(ext_filename, size,
 | 
					        if (vmdk_create_extent(ext_filename, size,
 | 
				
			||||||
                               flat, compress, zeroed_grain)) {
 | 
					                               flat, compress, zeroed_grain)) {
 | 
				
			||||||
            return -EINVAL;
 | 
					            ret = -EINVAL;
 | 
				
			||||||
 | 
					            goto exit;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        filesize -= size;
 | 
					        filesize -= size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* Format description line */
 | 
					        /* Format description line */
 | 
				
			||||||
        snprintf(desc_line, sizeof(desc_line),
 | 
					        snprintf(desc_line, sizeof(desc_line),
 | 
				
			||||||
                    desc_extent_line, size / 512, desc_filename);
 | 
					                    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 */
 | 
					    /* generate descriptor file */
 | 
				
			||||||
    snprintf(desc, sizeof(desc), desc_template,
 | 
					    desc = g_strdup_printf(desc_template,
 | 
				
			||||||
            (unsigned int)time(NULL),
 | 
					                           (unsigned int)time(NULL),
 | 
				
			||||||
            parent_cid,
 | 
					                           parent_cid,
 | 
				
			||||||
            fmt,
 | 
					                           fmt,
 | 
				
			||||||
            parent_desc_line,
 | 
					                           parent_desc_line,
 | 
				
			||||||
            ext_desc_lines,
 | 
					                           ext_desc_lines->str,
 | 
				
			||||||
            (flags & BLOCK_FLAG_COMPAT6 ? 6 : 4),
 | 
					                           (flags & BLOCK_FLAG_COMPAT6 ? 6 : 4),
 | 
				
			||||||
            total_size / (int64_t)(63 * number_heads * 512), number_heads,
 | 
					                           total_size / (int64_t)(63 * number_heads * 512),
 | 
				
			||||||
                adapter_type);
 | 
					                           number_heads,
 | 
				
			||||||
 | 
					                           adapter_type);
 | 
				
			||||||
    if (split || flat) {
 | 
					    if (split || flat) {
 | 
				
			||||||
        fd = qemu_open(filename,
 | 
					        fd = qemu_open(filename,
 | 
				
			||||||
                       O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE,
 | 
					                       O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE,
 | 
				
			||||||
@ -1767,21 +1777,25 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
 | 
				
			|||||||
                       0644);
 | 
					                       0644);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (fd < 0) {
 | 
					    if (fd < 0) {
 | 
				
			||||||
        return -errno;
 | 
					        ret = -errno;
 | 
				
			||||||
 | 
					        goto exit;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    /* the descriptor offset = 0x200 */
 | 
					    /* the descriptor offset = 0x200 */
 | 
				
			||||||
    if (!split && !flat && 0x200 != lseek(fd, 0x200, SEEK_SET)) {
 | 
					    if (!split && !flat && 0x200 != lseek(fd, 0x200, SEEK_SET)) {
 | 
				
			||||||
        ret = -errno;
 | 
					        ret = -errno;
 | 
				
			||||||
        goto exit;
 | 
					        goto close_exit;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    ret = qemu_write_full(fd, desc, strlen(desc));
 | 
					    ret = qemu_write_full(fd, desc, strlen(desc));
 | 
				
			||||||
    if (ret != strlen(desc)) {
 | 
					    if (ret != strlen(desc)) {
 | 
				
			||||||
        ret = -errno;
 | 
					        ret = -errno;
 | 
				
			||||||
        goto exit;
 | 
					        goto close_exit;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    ret = 0;
 | 
					    ret = 0;
 | 
				
			||||||
exit:
 | 
					close_exit:
 | 
				
			||||||
    qemu_close(fd);
 | 
					    qemu_close(fd);
 | 
				
			||||||
 | 
					exit:
 | 
				
			||||||
 | 
					    g_free(desc);
 | 
				
			||||||
 | 
					    g_string_free(ext_desc_lines, true);
 | 
				
			||||||
    return ret;
 | 
					    return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -75,6 +75,11 @@ echo
 | 
				
			|||||||
echo "=== Testing monolithicFlat with zeroed_grain ==="
 | 
					echo "=== Testing monolithicFlat with zeroed_grain ==="
 | 
				
			||||||
IMGOPTS="subformat=monolithicFlat,zeroed_grain=on" _make_test_img 2G
 | 
					IMGOPTS="subformat=monolithicFlat,zeroed_grain=on" _make_test_img 2G
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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/'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
echo
 | 
					echo
 | 
				
			||||||
echo "=== Testing version 3 ==="
 | 
					echo "=== Testing version 3 ==="
 | 
				
			||||||
_use_sample_img iotest-version3.vmdk.bz2
 | 
					_use_sample_img iotest-version3.vmdk.bz2
 | 
				
			||||||
 | 
				
			|||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user