 9e2e48ff31
			
		
	
	9e2e48ff31
	
	
	
		
			
			Its way more trouble to update this to a newer version of qemu than it is to backport the two additional features we need. Signed-off-by: Brett Mastbergen <bmastbergen@untangle.com>
		
			
				
	
	
		
			242 lines
		
	
	
		
			8.0 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			242 lines
		
	
	
		
			8.0 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| From 97cf5df76657bab81d6b8669607f6f13215201c1 Mon Sep 17 00:00:00 2001
 | |
| From: Fam Zheng <famcool@gmail.com>
 | |
| Date: Tue, 12 Jul 2011 19:56:31 +0800
 | |
| Subject: [PATCH 05/12] VMDK: separate vmdk_open by format version
 | |
| 
 | |
| Separate vmdk_open by subformats to:
 | |
| * vmdk_open_vmdk3
 | |
| * vmdk_open_vmdk4
 | |
| 
 | |
| Signed-off-by: Fam Zheng <famcool@gmail.com>
 | |
| Reviewed-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
 | |
| Signed-off-by: Kevin Wolf <kwolf@redhat.com>
 | |
| ---
 | |
|  block/vmdk.c | 178 +++++++++++++++++++++++++++++++++++++----------------------
 | |
|  1 file changed, 112 insertions(+), 66 deletions(-)
 | |
| 
 | |
| --- a/block/vmdk.c
 | |
| +++ b/block/vmdk.c
 | |
| @@ -458,67 +458,20 @@ static VmdkExtent *vmdk_add_extent(Block
 | |
|      return extent;
 | |
|  }
 | |
|  
 | |
| -
 | |
| -static int vmdk_open(BlockDriverState *bs, int flags)
 | |
| +static int vmdk_init_tables(BlockDriverState *bs, VmdkExtent *extent)
 | |
|  {
 | |
| -    BDRVVmdkState *s = bs->opaque;
 | |
| -    uint32_t magic;
 | |
| -    int i;
 | |
| -    uint32_t l1_size, l1_entry_sectors;
 | |
| -    VmdkExtent *extent = NULL;
 | |
| -
 | |
| -    if (bdrv_pread(bs->file, 0, &magic, sizeof(magic)) != sizeof(magic))
 | |
| -        goto fail;
 | |
| -
 | |
| -    magic = be32_to_cpu(magic);
 | |
| -    if (magic == VMDK3_MAGIC) {
 | |
| -        VMDK3Header header;
 | |
| -        if (bdrv_pread(bs->file, sizeof(magic), &header, sizeof(header))
 | |
| -                != sizeof(header)) {
 | |
| -            goto fail;
 | |
| -        }
 | |
| -        extent = vmdk_add_extent(bs, bs->file, false,
 | |
| -                              le32_to_cpu(header.disk_sectors),
 | |
| -                              le32_to_cpu(header.l1dir_offset) << 9, 0,
 | |
| -                              1 << 6, 1 << 9, le32_to_cpu(header.granularity));
 | |
| -    } else if (magic == VMDK4_MAGIC) {
 | |
| -        VMDK4Header header;
 | |
| -        if (bdrv_pread(bs->file, sizeof(magic), &header, sizeof(header))
 | |
| -                != sizeof(header)) {
 | |
| -            goto fail;
 | |
| -        }
 | |
| -        l1_entry_sectors = le32_to_cpu(header.num_gtes_per_gte)
 | |
| -                            * le64_to_cpu(header.granularity);
 | |
| -        l1_size = (le64_to_cpu(header.capacity) + l1_entry_sectors - 1)
 | |
| -                    / l1_entry_sectors;
 | |
| -        extent = vmdk_add_extent(bs, bs->file, false,
 | |
| -                              le64_to_cpu(header.capacity),
 | |
| -                              le64_to_cpu(header.gd_offset) << 9,
 | |
| -                              le64_to_cpu(header.rgd_offset) << 9,
 | |
| -                              l1_size,
 | |
| -                              le32_to_cpu(header.num_gtes_per_gte),
 | |
| -                              le64_to_cpu(header.granularity));
 | |
| -        if (extent->l1_entry_sectors <= 0) {
 | |
| -            goto fail;
 | |
| -        }
 | |
| -        // try to open parent images, if exist
 | |
| -        if (vmdk_parent_open(bs) != 0)
 | |
| -            goto fail;
 | |
| -        // write the CID once after the image creation
 | |
| -        s->parent_cid = vmdk_read_cid(bs,1);
 | |
| -    } else {
 | |
| -        goto fail;
 | |
| -    }
 | |
| +    int ret;
 | |
| +    int l1_size, i;
 | |
|  
 | |
|      /* read the L1 table */
 | |
|      l1_size = extent->l1_size * sizeof(uint32_t);
 | |
|      extent->l1_table = qemu_malloc(l1_size);
 | |
| -    if (bdrv_pread(bs->file,
 | |
| -            extent->l1_table_offset,
 | |
| -            extent->l1_table,
 | |
| -            l1_size)
 | |
| -        != l1_size) {
 | |
| -        goto fail;
 | |
| +    ret = bdrv_pread(extent->file,
 | |
| +                    extent->l1_table_offset,
 | |
| +                    extent->l1_table,
 | |
| +                    l1_size);
 | |
| +    if (ret < 0) {
 | |
| +        goto fail_l1;
 | |
|      }
 | |
|      for (i = 0; i < extent->l1_size; i++) {
 | |
|          le32_to_cpus(&extent->l1_table[i]);
 | |
| @@ -526,12 +479,12 @@ static int vmdk_open(BlockDriverState *b
 | |
|  
 | |
|      if (extent->l1_backup_table_offset) {
 | |
|          extent->l1_backup_table = qemu_malloc(l1_size);
 | |
| -        if (bdrv_pread(bs->file,
 | |
| -                    extent->l1_backup_table_offset,
 | |
| -                    extent->l1_backup_table,
 | |
| -                    l1_size)
 | |
| -                != l1_size) {
 | |
| -            goto fail;
 | |
| +        ret = bdrv_pread(extent->file,
 | |
| +                        extent->l1_backup_table_offset,
 | |
| +                        extent->l1_backup_table,
 | |
| +                        l1_size);
 | |
| +        if (ret < 0) {
 | |
| +            goto fail_l1b;
 | |
|          }
 | |
|          for (i = 0; i < extent->l1_size; i++) {
 | |
|              le32_to_cpus(&extent->l1_backup_table[i]);
 | |
| @@ -541,9 +494,102 @@ static int vmdk_open(BlockDriverState *b
 | |
|      extent->l2_cache =
 | |
|          qemu_malloc(extent->l2_size * L2_CACHE_SIZE * sizeof(uint32_t));
 | |
|      return 0;
 | |
| + fail_l1b:
 | |
| +    qemu_free(extent->l1_backup_table);
 | |
| + fail_l1:
 | |
| +    qemu_free(extent->l1_table);
 | |
| +    return ret;
 | |
| +}
 | |
| +
 | |
| +static int vmdk_open_vmdk3(BlockDriverState *bs, int flags)
 | |
| +{
 | |
| +    int ret;
 | |
| +    uint32_t magic;
 | |
| +    VMDK3Header header;
 | |
| +    VmdkExtent *extent;
 | |
| +
 | |
| +    ret = bdrv_pread(bs->file, sizeof(magic), &header, sizeof(header));
 | |
| +    if (ret < 0) {
 | |
| +        goto fail;
 | |
| +    }
 | |
| +    extent = vmdk_add_extent(bs,
 | |
| +                             bs->file, false,
 | |
| +                             le32_to_cpu(header.disk_sectors),
 | |
| +                             le32_to_cpu(header.l1dir_offset) << 9,
 | |
| +                             0, 1 << 6, 1 << 9,
 | |
| +                             le32_to_cpu(header.granularity));
 | |
| +    ret = vmdk_init_tables(bs, extent);
 | |
| +    if (ret) {
 | |
| +        /* vmdk_init_tables cleans up on fail, so only free allocation of
 | |
| +         * vmdk_add_extent here. */
 | |
| +        goto fail;
 | |
| +    }
 | |
| +    return 0;
 | |
|   fail:
 | |
|      vmdk_free_extents(bs);
 | |
| -    return -1;
 | |
| +    return ret;
 | |
| +}
 | |
| +
 | |
| +static int vmdk_open_vmdk4(BlockDriverState *bs, int flags)
 | |
| +{
 | |
| +    int ret;
 | |
| +    uint32_t magic;
 | |
| +    uint32_t l1_size, l1_entry_sectors;
 | |
| +    VMDK4Header header;
 | |
| +    BDRVVmdkState *s = bs->opaque;
 | |
| +    VmdkExtent *extent;
 | |
| +
 | |
| +    ret = bdrv_pread(bs->file, sizeof(magic), &header, sizeof(header));
 | |
| +    if (ret < 0) {
 | |
| +        goto fail;
 | |
| +    }
 | |
| +    l1_entry_sectors = le32_to_cpu(header.num_gtes_per_gte)
 | |
| +                        * le64_to_cpu(header.granularity);
 | |
| +    l1_size = (le64_to_cpu(header.capacity) + l1_entry_sectors - 1)
 | |
| +                / l1_entry_sectors;
 | |
| +    extent = vmdk_add_extent(bs, bs->file, false,
 | |
| +                          le64_to_cpu(header.capacity),
 | |
| +                          le64_to_cpu(header.gd_offset) << 9,
 | |
| +                          le64_to_cpu(header.rgd_offset) << 9,
 | |
| +                          l1_size,
 | |
| +                          le32_to_cpu(header.num_gtes_per_gte),
 | |
| +                          le64_to_cpu(header.granularity));
 | |
| +    if (extent->l1_entry_sectors <= 0) {
 | |
| +        ret = -EINVAL;
 | |
| +        goto fail;
 | |
| +    }
 | |
| +    /* try to open parent images, if exist */
 | |
| +    ret = vmdk_parent_open(bs);
 | |
| +    if (ret) {
 | |
| +        goto fail;
 | |
| +    }
 | |
| +    s->parent_cid = vmdk_read_cid(bs, 1);
 | |
| +    ret = vmdk_init_tables(bs, extent);
 | |
| +    if (ret) {
 | |
| +        goto fail;
 | |
| +    }
 | |
| +    return 0;
 | |
| + fail:
 | |
| +    vmdk_free_extents(bs);
 | |
| +    return ret;
 | |
| +}
 | |
| +
 | |
| +static int vmdk_open(BlockDriverState *bs, int flags)
 | |
| +{
 | |
| +    uint32_t magic;
 | |
| +
 | |
| +    if (bdrv_pread(bs->file, 0, &magic, sizeof(magic)) != sizeof(magic)) {
 | |
| +        return -EIO;
 | |
| +    }
 | |
| +
 | |
| +    magic = be32_to_cpu(magic);
 | |
| +    if (magic == VMDK3_MAGIC) {
 | |
| +        return vmdk_open_vmdk3(bs, flags);
 | |
| +    } else if (magic == VMDK4_MAGIC) {
 | |
| +        return vmdk_open_vmdk4(bs, flags);
 | |
| +    } else {
 | |
| +        return -EINVAL;
 | |
| +    }
 | |
|  }
 | |
|  
 | |
|  static int get_whole_cluster(BlockDriverState *bs,
 | |
| @@ -630,11 +676,11 @@ static uint64_t get_cluster_offset(Block
 | |
|      if (!l2_offset) {
 | |
|          return 0;
 | |
|      }
 | |
| -    for(i = 0; i < L2_CACHE_SIZE; i++) {
 | |
| +    for (i = 0; i < L2_CACHE_SIZE; i++) {
 | |
|          if (l2_offset == extent->l2_cache_offsets[i]) {
 | |
|              /* increment the hit count */
 | |
|              if (++extent->l2_cache_counts[i] == 0xffffffff) {
 | |
| -                for(j = 0; j < L2_CACHE_SIZE; j++) {
 | |
| +                for (j = 0; j < L2_CACHE_SIZE; j++) {
 | |
|                      extent->l2_cache_counts[j] >>= 1;
 | |
|                  }
 | |
|              }
 | |
| @@ -645,7 +691,7 @@ static uint64_t get_cluster_offset(Block
 | |
|      /* not found: load a new entry in the least used one */
 | |
|      min_index = 0;
 | |
|      min_count = 0xffffffff;
 | |
| -    for(i = 0; i < L2_CACHE_SIZE; i++) {
 | |
| +    for (i = 0; i < L2_CACHE_SIZE; i++) {
 | |
|          if (extent->l2_cache_counts[i] < min_count) {
 | |
|              min_count = extent->l2_cache_counts[i];
 | |
|              min_index = i;
 |