From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([140.186.70.92]:47581) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RsMxF-0006eI-3j for qemu-devel@nongnu.org; Tue, 31 Jan 2012 18:17:38 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1RsMxA-0005va-Fb for qemu-devel@nongnu.org; Tue, 31 Jan 2012 18:17:37 -0500 Received: from cantor2.suse.de ([195.135.220.15]:53796 helo=mx2.suse.de) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RsMxA-0005ue-0y for qemu-devel@nongnu.org; Tue, 31 Jan 2012 18:17:32 -0500 Message-ID: <4F2875FA.6090600@suse.de> Date: Wed, 01 Feb 2012 00:15:06 +0100 From: =?ISO-8859-1?Q?Andreas_F=E4rber?= MIME-Version: 1.0 References: <4F27D8A00200009100079C3A@novprvoes0310.provo.novell.com> <4F286659.6060300@suse.de> <4F2811220200009100079C4A@novprvoes0310.provo.novell.com> In-Reply-To: <4F2811220200009100079C4A@novprvoes0310.provo.novell.com> Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable Subject: Re: [Qemu-devel] [PATCH] block: Add support for vpc Fixed Disk type List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Charles Arnold Cc: Kevin Wolf , qemu-devel@nongnu.org Am 01.02.2012 00:04, schrieb Charles Arnold: > The Virtual Hard Disk Image Format Specification allows for three > types of hard disk formats, Fixed, Dynamic, and Differencing. Qemu=20 > currently only supports Dynamic disks. This patch adds support for > the Fixed Disk format. >=20 > Usage: > Example 1: qemu-img create -f vpc -o type=3Dfixed [size] > Example 2: qemu-img convert -O vpc -o type=3Dfixed = >=20 > While it is also allowed to specify '-o type=3Ddynamic', the default di= sk type=20 > remains Dynamic and is what is used when the type is left unspecified. >=20 > Signed-off-by: Charles Arnold Reviewed-by: Andreas F=E4rber Thanks, looking good now AFAICS. Andreas >=20 > diff --git a/block/vpc.c b/block/vpc.c =20 > index 89a5ee2..04db372 100644 =20 > --- a/block/vpc.c =20 > +++ b/block/vpc.c =20 > @@ -160,14 +160,25 @@ static int vpc_open(BlockDriverState *bs, int fla= gs) > struct vhd_dyndisk_header* dyndisk_header; = =20 > uint8_t buf[HEADER_SIZE]; = =20 > uint32_t checksum; = =20 > + int disk_type =3D VHD_DYNAMIC; = =20 > int err =3D -1; = =20 > = =20 > if (bdrv_pread(bs->file, 0, s->footer_buf, HEADER_SIZE) !=3D HEADE= R_SIZE) > goto fail; = =20 > = =20 > footer =3D (struct vhd_footer*) s->footer_buf; = =20 > - if (strncmp(footer->creator, "conectix", 8)) = =20 > - goto fail; = =20 > + if (strncmp(footer->creator, "conectix", 8)) { = =20 > + int64_t offset =3D bdrv_getlength(bs->file); = =20 > + /* If a fixed disk, the footer is found only at the end of the= file */ > + if (bdrv_pread(bs->file, offset-HEADER_SIZE, s->footer_buf, HE= ADER_SIZE) > + !=3D HEADER_SIZE) { = =20 > + goto fail; = =20 > + } = =20 > + if (strncmp(footer->creator, "conectix", 8)) { = =20 > + goto fail; = =20 > + } = =20 > + disk_type =3D VHD_FIXED; = =20 > + } = =20 > = =20 > checksum =3D be32_to_cpu(footer->checksum); = =20 > footer->checksum =3D 0; = =20 > @@ -186,6 +197,14 @@ static int vpc_open(BlockDriverState *bs, int flag= s) =20 > goto fail; = =20 > } = =20 > = =20 > + /* The footer is all that is needed for fixed disks */ = =20 > + if (disk_type =3D=3D VHD_FIXED) { = =20 > + /* The fixed disk format doesn't use footer->data_offset but i= t =20 > + should be initialized */ = =20 > + footer->data_offset =3D be64_to_cpu(0xFFFFFFFFFFFFFFFFULL); = =20 > + return 0; = =20 > + } = =20 > + = =20 > if (bdrv_pread(bs->file, be64_to_cpu(footer->data_offset), buf, HE= ADER_SIZE) > !=3D HEADER_SIZE) = =20 > goto fail; = =20 > @@ -533,10 +552,10 @@ static int calculate_geometry(int64_t total_secto= rs, uint16_t* cyls, > return 0; = =20 > } = =20 > = =20 > -static int vpc_create(const char *filename, QEMUOptionParameter *optio= ns) =20 > +static int vpc_create_dynamic_disk(const char *filename, int64_t total= _size) =20 > { = =20 > uint8_t buf[1024]; = =20 > - struct vhd_footer* footer =3D (struct vhd_footer*) buf; = =20 > + struct vhd_footer* footer =3D (struct vhd_footer *) buf; = =20 > struct vhd_dyndisk_header* dyndisk_header =3D = =20 > (struct vhd_dyndisk_header*) buf; = =20 > int fd, i; = =20 > @@ -544,13 +563,9 @@ static int vpc_create(const char *filename, QEMUOp= tionParameter *options) > uint8_t heads =3D 0; = =20 > uint8_t secs_per_cyl =3D 0; = =20 > size_t block_size, num_bat_entries; = =20 > - int64_t total_sectors =3D 0; = =20 > + int64_t total_sectors =3D total_size / BDRV_SECTOR_SIZE; = =20 > int ret =3D -EIO; = =20 > = =20 > - // Read out options = =20 > - total_sectors =3D get_option_parameter(options, BLOCK_OPT_SIZE)->v= alue.n / =20 > - BDRV_SECTOR_SIZE; = =20 > - = =20 > // Create the file = =20 > fd =3D open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 064= 4); =20 > if (fd < 0) = =20 > @@ -657,6 +672,101 @@ static int vpc_create(const char *filename, QEMUO= ptionParameter *options) > return ret; = =20 > } = =20 > = =20 > +static int vpc_create_fixed_disk(const char *filename, int64_t total_s= ize) =20 > +{ = =20 > + uint8_t buf[1024]; = =20 > + struct vhd_footer* footer =3D (struct vhd_footer *) buf; = =20 > + int fd; = =20 > + uint16_t cyls =3D 0; = =20 > + uint8_t heads =3D 0; = =20 > + uint8_t secs_per_cyl =3D 0; = =20 > + int64_t total_sectors =3D total_size / BDRV_SECTOR_SIZE; = =20 > + int ret =3D -EIO; = =20 > + = =20 > + /* Create the file */ = =20 > + fd =3D open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 064= 4); =20 > + if (fd < 0) { = =20 > + return -EIO; = =20 > + } = =20 > + = =20 > + /* Calculate matching total_size and geometry. */ = =20 > + if (calculate_geometry(total_sectors, &cyls, &heads, &secs_per_cyl= )) { =20 > + ret =3D -EFBIG; = =20 > + goto fail; = =20 > + } = =20 > + total_sectors =3D (int64_t) cyls * heads * secs_per_cyl; = =20 > + = =20 > + /* Prepare the Hard Disk Footer */ = =20 > + memset(buf, 0, 1024); = =20 > + = =20 > + memcpy(footer->creator, "conectix", 8); = =20 > + /* TODO Check if "qemu" creator_app is ok for VPC */ = =20 > + memcpy(footer->creator_app, "qemu", 4); = =20 > + memcpy(footer->creator_os, "Wi2k", 4); = =20 > + = =20 > + footer->features =3D be32_to_cpu(0x02); = =20 > + footer->version =3D be32_to_cpu(0x00010000); = =20 > + footer->data_offset =3D be64_to_cpu(0xFFFFFFFFFFFFFFFFULL); = =20 > + footer->timestamp =3D be32_to_cpu(time(NULL) - VHD_TIMESTAMP_BASE)= ; =20 > + = =20 > + /* Version of Virtual PC 2007 */ = =20 > + footer->major =3D be16_to_cpu(0x0005); = =20 > + footer->minor =3D be16_to_cpu(0x0003); = =20 > + footer->orig_size =3D be64_to_cpu(total_size); = =20 > + footer->size =3D be64_to_cpu(total_size); = =20 > + footer->cyls =3D be16_to_cpu(cyls); = =20 > + footer->heads =3D heads; = =20 > + footer->secs_per_cyl =3D secs_per_cyl; = =20 > + = =20 > + footer->type =3D be32_to_cpu(VHD_FIXED); = =20 > + = =20 > + /* TODO uuid is missing */ = =20 > + = =20 > + footer->checksum =3D be32_to_cpu(vpc_checksum(buf, HEADER_SIZE)); = =20 > + = =20 > + total_size +=3D 512; = =20 > + if (ftruncate(fd, total_size) !=3D 0) { = =20 > + ret =3D -errno; = =20 > + goto fail; = =20 > + } = =20 > + if (lseek(fd, -512, SEEK_END) < 0) { = =20 > + goto fail; = =20 > + } = =20 > + if (write(fd, buf, HEADER_SIZE) !=3D HEADER_SIZE) { > + goto fail; > + } > + > + ret =3D 0; > + > + fail: > + close(fd); > + return ret; > +} > + > +static int vpc_create(const char *filename, QEMUOptionParameter *optio= ns) > +{ > + int64_t total_size =3D 0; > + QEMUOptionParameter *disk_type_param; > + int ret =3D -EIO; > + > + /* Read out options */ > + total_size =3D get_option_parameter(options, BLOCK_OPT_SIZE)->valu= e.n; > + > + disk_type_param =3D get_option_parameter(options, BLOCK_OPT_TYPE); > + if (disk_type_param && disk_type_param->value.s) { > + if (!strcmp(disk_type_param->value.s, "dynamic")) { > + ret =3D vpc_create_dynamic_disk(filename, total_size); > + } else if (!strcmp(disk_type_param->value.s, "fixed")) { > + ret =3D vpc_create_fixed_disk(filename, total_size); > + } else { > + ret =3D -EINVAL; > + } > + } else { > + ret =3D vpc_create_dynamic_disk(filename, total_size); > + } > + return ret; > +} > + > static void vpc_close(BlockDriverState *bs) > { > BDRVVPCState *s =3D bs->opaque; > @@ -675,6 +785,13 @@ static QEMUOptionParameter vpc_create_options[] =3D= { > .type =3D OPT_SIZE, > .help =3D "Virtual disk size" > }, > + { > + .name =3D BLOCK_OPT_TYPE, > + .type =3D OPT_STRING, > + .help =3D > + "Type of virtual hard disk format. Supported formats are " > + "{dynamic (default) | fixed} " > + }, > { NULL } > }; >=20 > diff --git a/block_int.h b/block_int.h > index 311bd2a..6d6cc96 100644 > --- a/block_int.h > +++ b/block_int.h > @@ -50,6 +50,7 @@ > #define BLOCK_OPT_TABLE_SIZE "table_size" > #define BLOCK_OPT_PREALLOC "preallocation" > #define BLOCK_OPT_SUBFMT "subformat" > +#define BLOCK_OPT_TYPE "type" >=20 > typedef struct BdrvTrackedRequest BdrvTrackedRequest; >=20 --=20 SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 N=FCrnberg, Germany GF: Jeff Hawn, Jennifer Guild, Felix Imend=F6rffer; HRB 16746 AG N=FCrnbe= rg