Commit 2d22b18f77ab0a488762e9216575b8582f1adb7d

Authored by aliguori
1 parent 40a2d705

Fix handling of disk-only snapshots (Kevin Wolf)

When creating a snapshot with multiple qcow2 disks attached, the current
behaviour is that qemu creates a disk snapshot on all of them and
chooses one to write the VM state to.

Despite having the state only in one image, loadvm tries to restore the
VM state from the middle of nowhere if you run qemu a second time with
only one of the other images attached. In the lucky case it will fail
because there simply is no state, but it also can happen that it loads
the state of a different snapshot (the one this new one is based upon).

The fix is to write a zero VM state size to the images which don't
contain the state, and check this in loadvm.

I agree that you probably have to provoke such things intentionally to
get in a state like this with qemu itself. However, with my second patch
that adds snapshot support to qemu-img it could become a reasonable use
case to have snapshots with and without VM states on the same image.

Signed-off-by: Kevin Wolf <kwolf@suse.de>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>



git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5985 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 10 additions and 1 deletions
savevm.c
... ... @@ -1020,6 +1020,7 @@ void do_savevm(const char *name)
1020 1020 BlockDriverInfo bdi1, *bdi = &bdi1;
1021 1021 QEMUFile *f;
1022 1022 int saved_vm_running;
  1023 + uint32_t vm_state_size;
1023 1024 #ifdef _WIN32
1024 1025 struct _timeb tb;
1025 1026 #else
... ... @@ -1079,7 +1080,7 @@ void do_savevm(const char *name)
1079 1080 goto the_end;
1080 1081 }
1081 1082 ret = qemu_savevm_state(f);
1082   - sn->vm_state_size = qemu_ftell(f);
  1083 + vm_state_size = qemu_ftell(f);
1083 1084 qemu_fclose(f);
1084 1085 if (ret < 0) {
1085 1086 term_printf("Error %d while writing VM\n", ret);
... ... @@ -1098,6 +1099,8 @@ void do_savevm(const char *name)
1098 1099 bdrv_get_device_name(bs1));
1099 1100 }
1100 1101 }
  1102 + /* Write VM state size only to the image that contains the state */
  1103 + sn->vm_state_size = (bs == bs1 ? vm_state_size : 0);
1101 1104 ret = bdrv_snapshot_create(bs1, sn);
1102 1105 if (ret < 0) {
1103 1106 term_printf("Error while creating snapshot on '%s'\n",
... ... @@ -1115,6 +1118,7 @@ void do_loadvm(const char *name)
1115 1118 {
1116 1119 BlockDriverState *bs, *bs1;
1117 1120 BlockDriverInfo bdi1, *bdi = &bdi1;
  1121 + QEMUSnapshotInfo sn;
1118 1122 QEMUFile *f;
1119 1123 int i, ret;
1120 1124 int saved_vm_running;
... ... @@ -1165,6 +1169,11 @@ void do_loadvm(const char *name)
1165 1169 return;
1166 1170 }
1167 1171  
  1172 + /* Don't even try to load empty VM states */
  1173 + ret = bdrv_snapshot_find(bs, &sn, name);
  1174 + if ((ret >= 0) && (sn.vm_state_size == 0))
  1175 + goto the_end;
  1176 +
1168 1177 /* restore the VM state */
1169 1178 f = qemu_fopen_bdrv(bs, bdi->vm_state_offset, 0);
1170 1179 if (!f) {
... ...