Revision 45566e9c
b/block.c | ||
---|---|---|
1158 | 1158 |
return drv->bdrv_get_info(bs, bdi); |
1159 | 1159 |
} |
1160 | 1160 |
|
1161 |
int bdrv_put_buffer(BlockDriverState *bs, const uint8_t *buf, int64_t pos, int size) |
|
1161 |
int bdrv_save_vmstate(BlockDriverState *bs, const uint8_t *buf, |
|
1162 |
int64_t pos, int size) |
|
1162 | 1163 |
{ |
1163 | 1164 |
BlockDriver *drv = bs->drv; |
1164 | 1165 |
if (!drv) |
1165 | 1166 |
return -ENOMEDIUM; |
1166 |
if (!drv->bdrv_put_buffer)
|
|
1167 |
if (!drv->bdrv_save_vmstate)
|
|
1167 | 1168 |
return -ENOTSUP; |
1168 |
return drv->bdrv_put_buffer(bs, buf, pos, size);
|
|
1169 |
return drv->bdrv_save_vmstate(bs, buf, pos, size);
|
|
1169 | 1170 |
} |
1170 | 1171 |
|
1171 |
int bdrv_get_buffer(BlockDriverState *bs, uint8_t *buf, int64_t pos, int size) |
|
1172 |
int bdrv_load_vmstate(BlockDriverState *bs, uint8_t *buf, |
|
1173 |
int64_t pos, int size) |
|
1172 | 1174 |
{ |
1173 | 1175 |
BlockDriver *drv = bs->drv; |
1174 | 1176 |
if (!drv) |
1175 | 1177 |
return -ENOMEDIUM; |
1176 |
if (!drv->bdrv_get_buffer)
|
|
1178 |
if (!drv->bdrv_load_vmstate)
|
|
1177 | 1179 |
return -ENOTSUP; |
1178 |
return drv->bdrv_get_buffer(bs, buf, pos, size);
|
|
1180 |
return drv->bdrv_load_vmstate(bs, buf, pos, size);
|
|
1179 | 1181 |
} |
1180 | 1182 |
|
1181 | 1183 |
/**************************************************************/ |
b/block.h | ||
---|---|---|
159 | 159 |
const char *base_path, |
160 | 160 |
const char *filename); |
161 | 161 |
|
162 |
int bdrv_put_buffer(BlockDriverState *bs, const uint8_t *buf,
|
|
163 |
int64_t pos, int size); |
|
162 |
int bdrv_save_vmstate(BlockDriverState *bs, const uint8_t *buf,
|
|
163 |
int64_t pos, int size);
|
|
164 | 164 |
|
165 |
int bdrv_get_buffer(BlockDriverState *bs, uint8_t *buf, int64_t pos, int size); |
|
165 |
int bdrv_load_vmstate(BlockDriverState *bs, uint8_t *buf, |
|
166 |
int64_t pos, int size); |
|
166 | 167 |
|
167 | 168 |
#endif |
b/block/qcow2.c | ||
---|---|---|
890 | 890 |
bdrv_flush(s->hd); |
891 | 891 |
} |
892 | 892 |
|
893 |
static int64_t qcow_vm_state_offset(BDRVQcowState *s) |
|
894 |
{ |
|
895 |
return (int64_t)s->l1_vm_state_index << (s->cluster_bits + s->l2_bits); |
|
896 |
} |
|
897 |
|
|
893 | 898 |
static int qcow_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) |
894 | 899 |
{ |
895 | 900 |
BDRVQcowState *s = bs->opaque; |
896 | 901 |
bdi->cluster_size = s->cluster_size; |
897 |
bdi->vm_state_offset = (int64_t)s->l1_vm_state_index << |
|
898 |
(s->cluster_bits + s->l2_bits); |
|
902 |
bdi->vm_state_offset = qcow_vm_state_offset(s); |
|
899 | 903 |
return 0; |
900 | 904 |
} |
901 | 905 |
|
... | ... | |
925 | 929 |
} |
926 | 930 |
#endif |
927 | 931 |
|
928 |
static int qcow_put_buffer(BlockDriverState *bs, const uint8_t *buf,
|
|
932 |
static int qcow_save_vmstate(BlockDriverState *bs, const uint8_t *buf,
|
|
929 | 933 |
int64_t pos, int size) |
930 | 934 |
{ |
935 |
BDRVQcowState *s = bs->opaque; |
|
931 | 936 |
int growable = bs->growable; |
932 | 937 |
|
933 | 938 |
bs->growable = 1; |
934 |
bdrv_pwrite(bs, pos, buf, size); |
|
939 |
bdrv_pwrite(bs, qcow_vm_state_offset(s) + pos, buf, size);
|
|
935 | 940 |
bs->growable = growable; |
936 | 941 |
|
937 | 942 |
return size; |
938 | 943 |
} |
939 | 944 |
|
940 |
static int qcow_get_buffer(BlockDriverState *bs, uint8_t *buf,
|
|
945 |
static int qcow_load_vmstate(BlockDriverState *bs, uint8_t *buf,
|
|
941 | 946 |
int64_t pos, int size) |
942 | 947 |
{ |
948 |
BDRVQcowState *s = bs->opaque; |
|
943 | 949 |
int growable = bs->growable; |
944 | 950 |
int ret; |
945 | 951 |
|
946 | 952 |
bs->growable = 1; |
947 |
ret = bdrv_pread(bs, pos, buf, size); |
|
953 |
ret = bdrv_pread(bs, qcow_vm_state_offset(s) + pos, buf, size);
|
|
948 | 954 |
bs->growable = growable; |
949 | 955 |
|
950 | 956 |
return ret; |
... | ... | |
1001 | 1007 |
.bdrv_snapshot_list = qcow2_snapshot_list, |
1002 | 1008 |
.bdrv_get_info = qcow_get_info, |
1003 | 1009 |
|
1004 |
.bdrv_put_buffer = qcow_put_buffer,
|
|
1005 |
.bdrv_get_buffer = qcow_get_buffer,
|
|
1010 |
.bdrv_save_vmstate = qcow_save_vmstate,
|
|
1011 |
.bdrv_load_vmstate = qcow_load_vmstate,
|
|
1006 | 1012 |
|
1007 | 1013 |
.create_options = qcow_create_options, |
1008 | 1014 |
.bdrv_check = qcow_check, |
b/block_int.h | ||
---|---|---|
84 | 84 |
QEMUSnapshotInfo **psn_info); |
85 | 85 |
int (*bdrv_get_info)(BlockDriverState *bs, BlockDriverInfo *bdi); |
86 | 86 |
|
87 |
int (*bdrv_put_buffer)(BlockDriverState *bs, const uint8_t *buf,
|
|
88 |
int64_t pos, int size); |
|
89 |
int (*bdrv_get_buffer)(BlockDriverState *bs, uint8_t *buf,
|
|
90 |
int64_t pos, int size); |
|
87 |
int (*bdrv_save_vmstate)(BlockDriverState *bs, const uint8_t *buf,
|
|
88 |
int64_t pos, int size);
|
|
89 |
int (*bdrv_load_vmstate)(BlockDriverState *bs, uint8_t *buf,
|
|
90 |
int64_t pos, int size);
|
|
91 | 91 |
|
92 | 92 |
/* removable device specific */ |
93 | 93 |
int (*bdrv_is_inserted)(BlockDriverState *bs); |
b/savevm.c | ||
---|---|---|
337 | 337 |
return NULL; |
338 | 338 |
} |
339 | 339 |
|
340 |
typedef struct QEMUFileBdrv |
|
341 |
{ |
|
342 |
BlockDriverState *bs; |
|
343 |
int64_t base_offset; |
|
344 |
} QEMUFileBdrv; |
|
345 |
|
|
346 | 340 |
static int block_put_buffer(void *opaque, const uint8_t *buf, |
347 | 341 |
int64_t pos, int size) |
348 | 342 |
{ |
349 |
QEMUFileBdrv *s = opaque; |
|
350 |
bdrv_put_buffer(s->bs, buf, s->base_offset + pos, size); |
|
343 |
bdrv_save_vmstate(opaque, buf, pos, size); |
|
351 | 344 |
return size; |
352 | 345 |
} |
353 | 346 |
|
354 | 347 |
static int block_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size) |
355 | 348 |
{ |
356 |
QEMUFileBdrv *s = opaque; |
|
357 |
return bdrv_get_buffer(s->bs, buf, s->base_offset + pos, size); |
|
349 |
return bdrv_load_vmstate(opaque, buf, pos, size); |
|
358 | 350 |
} |
359 | 351 |
|
360 | 352 |
static int bdrv_fclose(void *opaque) |
361 | 353 |
{ |
362 |
QEMUFileBdrv *s = opaque; |
|
363 |
qemu_free(s); |
|
364 | 354 |
return 0; |
365 | 355 |
} |
366 | 356 |
|
367 |
static QEMUFile *qemu_fopen_bdrv(BlockDriverState *bs, int64_t offset, int is_writable)
|
|
357 |
static QEMUFile *qemu_fopen_bdrv(BlockDriverState *bs, int is_writable) |
|
368 | 358 |
{ |
369 |
QEMUFileBdrv *s; |
|
370 |
|
|
371 |
s = qemu_mallocz(sizeof(QEMUFileBdrv)); |
|
372 |
|
|
373 |
s->bs = bs; |
|
374 |
s->base_offset = offset; |
|
375 |
|
|
376 | 359 |
if (is_writable) |
377 |
return qemu_fopen_ops(s, block_put_buffer, NULL, bdrv_fclose, NULL, NULL); |
|
378 |
|
|
379 |
return qemu_fopen_ops(s, NULL, block_get_buffer, bdrv_fclose, NULL, NULL); |
|
360 |
return qemu_fopen_ops(bs, block_put_buffer, NULL, bdrv_fclose, NULL, NULL); |
|
361 |
return qemu_fopen_ops(bs, NULL, block_get_buffer, bdrv_fclose, NULL, NULL); |
|
380 | 362 |
} |
381 | 363 |
|
382 | 364 |
QEMUFile *qemu_fopen_ops(void *opaque, QEMUFilePutBufferFunc *put_buffer, |
... | ... | |
1069 | 1051 |
BlockDriverState *bs, *bs1; |
1070 | 1052 |
QEMUSnapshotInfo sn1, *sn = &sn1, old_sn1, *old_sn = &old_sn1; |
1071 | 1053 |
int must_delete, ret, i; |
1072 |
BlockDriverInfo bdi1, *bdi = &bdi1; |
|
1073 | 1054 |
QEMUFile *f; |
1074 | 1055 |
int saved_vm_running; |
1075 | 1056 |
uint32_t vm_state_size; |
... | ... | |
1119 | 1100 |
#endif |
1120 | 1101 |
sn->vm_clock_nsec = qemu_get_clock(vm_clock); |
1121 | 1102 |
|
1122 |
if (bdrv_get_info(bs, bdi) < 0 || bdi->vm_state_offset <= 0) { |
|
1123 |
monitor_printf(mon, "Device %s does not support VM state snapshots\n", |
|
1124 |
bdrv_get_device_name(bs)); |
|
1125 |
goto the_end; |
|
1126 |
} |
|
1127 |
|
|
1128 | 1103 |
/* save the VM state */ |
1129 |
f = qemu_fopen_bdrv(bs, bdi->vm_state_offset, 1);
|
|
1104 |
f = qemu_fopen_bdrv(bs, 1); |
|
1130 | 1105 |
if (!f) { |
1131 | 1106 |
monitor_printf(mon, "Could not open VM state file\n"); |
1132 | 1107 |
goto the_end; |
... | ... | |
1170 | 1145 |
void do_loadvm(Monitor *mon, const char *name) |
1171 | 1146 |
{ |
1172 | 1147 |
BlockDriverState *bs, *bs1; |
1173 |
BlockDriverInfo bdi1, *bdi = &bdi1; |
|
1174 | 1148 |
QEMUSnapshotInfo sn; |
1175 | 1149 |
QEMUFile *f; |
1176 | 1150 |
int i, ret; |
... | ... | |
1218 | 1192 |
} |
1219 | 1193 |
} |
1220 | 1194 |
|
1221 |
if (bdrv_get_info(bs, bdi) < 0 || bdi->vm_state_offset <= 0) { |
|
1222 |
monitor_printf(mon, "Device %s does not support VM state snapshots\n", |
|
1223 |
bdrv_get_device_name(bs)); |
|
1224 |
return; |
|
1225 |
} |
|
1226 |
|
|
1227 | 1195 |
/* Don't even try to load empty VM states */ |
1228 | 1196 |
ret = bdrv_snapshot_find(bs, &sn, name); |
1229 | 1197 |
if ((ret >= 0) && (sn.vm_state_size == 0)) |
1230 | 1198 |
goto the_end; |
1231 | 1199 |
|
1232 | 1200 |
/* restore the VM state */ |
1233 |
f = qemu_fopen_bdrv(bs, bdi->vm_state_offset, 0);
|
|
1201 |
f = qemu_fopen_bdrv(bs, 0); |
|
1234 | 1202 |
if (!f) { |
1235 | 1203 |
monitor_printf(mon, "Could not open VM state file\n"); |
1236 | 1204 |
goto the_end; |
Also available in: Unified diff