]> git.proxmox.com Git - qemu.git/commitdiff
qcow2: Save disk size in snapshot header
authorKevin Wolf <kwolf@redhat.com>
Wed, 11 Apr 2012 14:33:50 +0000 (16:33 +0200)
committerKevin Wolf <kwolf@redhat.com>
Fri, 20 Apr 2012 13:57:27 +0000 (15:57 +0200)
This allows that different snapshots of an image can have different
sizes, which is a requirement for enabling image resizing even with
images that have internal snapshots.

We don't do the actual support for it now, but make sure that the
additional field is present and not completely ignored in all version 3
images. When trying to load a snapshot of different size, it returns
an error.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
block/qcow2-snapshot.c
block/qcow2.h

index 7d3fde5a8acbbac570f13f70330274db9c7db4d0..42f971b590930c2fb6a0a432e76a94a903e359ad 100644 (file)
@@ -48,6 +48,7 @@ typedef struct QEMU_PACKED QCowSnapshotHeader {
 
 typedef struct QEMU_PACKED QCowSnapshotExtraData {
     uint64_t vm_state_size_large;
+    uint64_t disk_size;
 } QCowSnapshotExtraData;
 
 void qcow2_free_snapshots(BlockDriverState *bs)
@@ -117,6 +118,12 @@ int qcow2_read_snapshots(BlockDriverState *bs)
             sn->vm_state_size = be64_to_cpu(extra.vm_state_size_large);
         }
 
+        if (extra_data_size >= 16) {
+            sn->disk_size = be64_to_cpu(extra.disk_size);
+        } else {
+            sn->disk_size = bs->total_sectors * BDRV_SECTOR_SIZE;
+        }
+
         /* Read snapshot ID */
         sn->id_str = g_malloc(id_str_size + 1);
         ret = bdrv_pread(bs->file, offset, sn->id_str, id_str_size);
@@ -197,6 +204,7 @@ static int qcow2_write_snapshots(BlockDriverState *bs)
 
         memset(&extra, 0, sizeof(extra));
         extra.vm_state_size_large = cpu_to_be64(sn->vm_state_size);
+        extra.disk_size = cpu_to_be64(sn->disk_size);
 
         id_str_size = strlen(sn->id_str);
         name_size = strlen(sn->name);
@@ -330,6 +338,7 @@ int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
     sn->id_str = g_strdup(sn_info->id_str);
     sn->name = g_strdup(sn_info->name);
 
+    sn->disk_size = bs->total_sectors * BDRV_SECTOR_SIZE;
     sn->vm_state_size = sn_info->vm_state_size;
     sn->date_sec = sn_info->date_sec;
     sn->date_nsec = sn_info->date_nsec;
@@ -426,6 +435,13 @@ int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
     }
     sn = &s->snapshots[snapshot_index];
 
+    if (sn->disk_size != bs->total_sectors * BDRV_SECTOR_SIZE) {
+        error_report("qcow2: Loading snapshots with different disk "
+            "size is not implemented");
+        ret = -ENOTSUP;
+        goto fail;
+    }
+
     /*
      * Make sure that the current L1 table is big enough to contain the whole
      * L1 table of the snapshot. If the snapshot L1 table is smaller, the
index e4ac366cfcfbb3ac45b0edb26add23a91241a678..ddb976a75908ba8911b7973882103bd9bcb9f9ff 100644 (file)
@@ -78,6 +78,7 @@ typedef struct QCowSnapshot {
     uint32_t l1_size;
     char *id_str;
     char *name;
+    uint64_t disk_size;
     uint64_t vm_state_size;
     uint32_t date_sec;
     uint32_t date_nsec;