]> git.proxmox.com Git - pve-qemu-kvm.git/blame - debian/patches/internal-snapshot.patch
snapshot_start: use bdrv instead of file
[pve-qemu-kvm.git] / debian / patches / internal-snapshot.patch
CommitLineData
7378b84a
DM
1Index: new/qapi-schema.json
2===================================================================
5db17e8c
DM
3--- new.orig/qapi-schema.json 2012-09-07 07:41:45.000000000 +0200
4+++ new/qapi-schema.json 2012-09-13 09:22:06.000000000 +0200
71788d62 5@@ -2493,3 +2493,12 @@
7378b84a
DM
6 # Since: 1.2.0
7 ##
8 { 'command': 'query-target', 'returns': 'TargetInfo' }
9+
10+
71788d62 11+{ 'command': 'snapshot-start' 'data': { '*statefile': 'str' } }
7378b84a
DM
12+
13+{ 'command': 'snapshot-drive', 'data': { 'device': 'str', 'name': 'str' } }
14+
71788d62
DM
15+{ 'command': 'delete-drive-snapshot', 'data': { 'device': 'str', 'name': 'str' } }
16+
7378b84a
DM
17+{ 'command': 'snapshot-end' }
18Index: new/qmp.c
19===================================================================
5db17e8c 20--- new.orig/qmp.c 2012-09-07 07:41:45.000000000 +0200
49adae7d
DM
21+++ new/qmp.c 2012-09-14 14:06:56.000000000 +0200
22@@ -479,3 +479,224 @@
7378b84a
DM
23 return arch_query_cpu_definitions(errp);
24 }
25
26+static struct SnapshotState {
27+ int in_progress;
28+ int saved_vm_running;
29+} snap_state;
30+
49adae7d
DM
31+static int block_put_buffer(void *opaque, const uint8_t *buf,
32+ int64_t pos, int size)
33+{
34+ bdrv_pwrite(opaque, pos, buf, size);
35+ return size;
36+}
37+
38+static int bdrv_fclose(void *opaque)
39+{
40+ return bdrv_flush(opaque);
41+}
42+
71788d62 43+void qmp_snapshot_start(bool has_statefile, const char *statefile, Error **errp)
7378b84a 44+{
49adae7d
DM
45+ BlockDriverState *bs = NULL;
46+ BlockDriver *drv = NULL;
47+ int bdrv_oflags = BDRV_O_NOCACHE | BDRV_O_RDWR;
7378b84a
DM
48+ QEMUFile *f;
49+ int ret;
50+
51+ if (snap_state.in_progress) {
52+ error_set(errp, ERROR_CLASS_GENERIC_ERROR,
53+ "VM snapshot already started\n");
54+ return;
55+ }
e3a98889 56+
7378b84a
DM
57+ snap_state.in_progress = 1;
58+
59+ snap_state.saved_vm_running = runstate_is_running();
60+
61+ vm_stop(RUN_STATE_SAVE_VM);
62+
71788d62
DM
63+ if (!has_statefile)
64+ return;
65+
49adae7d
DM
66+ /* Open the image */
67+ bs = bdrv_new("vmstate");
68+ ret = bdrv_open(bs, statefile, bdrv_oflags, drv);
69+ if (ret < 0) {
70+ error_set(errp, QERR_OPEN_FILE_FAILED, statefile);
71+ goto restart;
72+ }
73+
74+ f = qemu_fopen_ops(bs, block_put_buffer, NULL, bdrv_fclose,
75+ NULL, NULL, NULL);
7378b84a
DM
76+ if (!f) {
77+ error_set(errp, QERR_OPEN_FILE_FAILED, statefile);
e3a98889 78+ goto restart;
7378b84a
DM
79+ }
80+
e3a98889 81+ ret = qemu_savevm_state(f);
49adae7d
DM
82+
83+ bdrv_truncate(bs, qemu_ftell(f)); // ignore errors
84+
7378b84a 85+ qemu_fclose(f);
49adae7d 86+
7378b84a
DM
87+ if (ret < 0) {
88+ error_set(errp, ERROR_CLASS_GENERIC_ERROR,
89+ "Error %d while writing VM state\n", ret);
49adae7d 90+ goto restart;
e3a98889 91+ }
49adae7d
DM
92+end:
93+ if (bs)
94+ bdrv_delete(bs);
e3a98889
DM
95+
96+ return;
97+
98+restart:
99+
100+ snap_state.in_progress = 0;
101+
102+ if (snap_state.saved_vm_running) {
103+ vm_start();
7378b84a 104+ }
49adae7d
DM
105+
106+ goto end;
7378b84a
DM
107+}
108+
109+void qmp_snapshot_end(Error **errp)
110+{
111+ if (!snap_state.in_progress) {
112+ error_set(errp, ERROR_CLASS_GENERIC_ERROR,
113+ "VM snapshot not started\n");
114+ return;
115+ }
116+ snap_state.in_progress = 0;
117+
118+ if (snap_state.saved_vm_running) {
119+ vm_start();
120+ }
121+}
122+
123+/* Fixme: Copied from savevm */
124+static int bdrv_snapshot_find(BlockDriverState *bs, QEMUSnapshotInfo *sn_info,
125+ const char *name)
126+{
127+ QEMUSnapshotInfo *sn_tab, *sn;
128+ int nb_sns, i, ret;
129+
130+ ret = -ENOENT;
131+ nb_sns = bdrv_snapshot_list(bs, &sn_tab);
132+ if (nb_sns < 0)
133+ return ret;
134+ for(i = 0; i < nb_sns; i++) {
135+ sn = &sn_tab[i];
136+ if (!strcmp(sn->id_str, name) || !strcmp(sn->name, name)) {
137+ *sn_info = *sn;
138+ ret = 0;
139+ break;
140+ }
141+ }
142+ g_free(sn_tab);
143+ return ret;
144+}
145+
146+void qmp_snapshot_drive(const char *device, const char *name, Error **errp)
147+{
148+ BlockDriverState *bs;
149+ QEMUSnapshotInfo sn1, *sn = &sn1;
150+ int ret;
151+#ifdef _WIN32
152+ struct _timeb tb;
153+#else
154+ struct timeval tv;
155+#endif
156+
157+ if (!snap_state.in_progress) {
158+ error_set(errp, ERROR_CLASS_GENERIC_ERROR,
159+ "VM snapshot not started\n");
160+ return;
161+ }
162+
163+ bs = bdrv_find(device);
164+ if (!bs) {
165+ error_set(errp, QERR_DEVICE_NOT_FOUND, device);
166+ return;
167+ }
168+
169+ if (!bdrv_is_inserted(bs)) {
170+ error_set(errp, QERR_DEVICE_HAS_NO_MEDIUM, device);
171+ return;
172+ }
173+
174+ if (bdrv_is_read_only(bs)) {
175+ error_set(errp, QERR_DEVICE_IS_READ_ONLY, device);
176+ return;
177+ }
178+
179+ if (!bdrv_can_snapshot(bs)) {
180+ error_set(errp, QERR_NOT_SUPPORTED);
181+ return;
182+ }
183+
184+ if (bdrv_snapshot_find(bs, sn, name) >= 0) {
185+ error_set(errp, ERROR_CLASS_GENERIC_ERROR,
186+ "snapshot '%s' already exists", name);
187+ return;
188+ }
189+
190+ sn = &sn1;
191+ memset(sn, 0, sizeof(*sn));
192+
193+#ifdef _WIN32
194+ _ftime(&tb);
195+ sn->date_sec = tb.time;
196+ sn->date_nsec = tb.millitm * 1000000;
197+#else
198+ gettimeofday(&tv, NULL);
199+ sn->date_sec = tv.tv_sec;
200+ sn->date_nsec = tv.tv_usec * 1000;
201+#endif
202+ sn->vm_clock_nsec = qemu_get_clock_ns(vm_clock);
203+
204+ pstrcpy(sn->name, sizeof(sn->name), name);
205+
206+ sn->vm_state_size = 0; /* do not save state */
207+
208+ ret = bdrv_snapshot_create(bs, sn);
209+ if (ret < 0) {
210+ error_set(errp, ERROR_CLASS_GENERIC_ERROR, "Error while creating snapshot on '%s'\n", device);
211+ return;
212+ }
213+}
71788d62
DM
214+
215+void qmp_delete_drive_snapshot(const char *device, const char *name, Error **errp)
216+{
217+ BlockDriverState *bs;
218+ QEMUSnapshotInfo sn1, *sn = &sn1;
219+ int ret;
220+
221+ bs = bdrv_find(device);
222+ if (!bs) {
223+ error_set(errp, QERR_DEVICE_NOT_FOUND, device);
224+ return;
225+ }
226+ if (bdrv_is_read_only(bs)) {
227+ error_set(errp, QERR_DEVICE_IS_READ_ONLY, device);
228+ return;
229+ }
230+
231+ if (!bdrv_can_snapshot(bs)) {
232+ error_set(errp, QERR_NOT_SUPPORTED);
233+ return;
234+ }
235+
236+ if (bdrv_snapshot_find(bs, sn, name) < 0) {
237+ /* return success if snapshot does not exists */
238+ return;
239+ }
240+
241+ ret = bdrv_snapshot_delete(bs, name);
242+ if (ret < 0) {
243+ error_set(errp, ERROR_CLASS_GENERIC_ERROR, "Error while deleting snapshot on '%s'\n", device);
244+ return;
245+ }
246+}
7378b84a
DM
247Index: new/qmp-commands.hx
248===================================================================
5db17e8c
DM
249--- new.orig/qmp-commands.hx 2012-09-07 07:41:45.000000000 +0200
250+++ new/qmp-commands.hx 2012-09-13 09:30:33.000000000 +0200
71788d62 251@@ -2514,3 +2514,27 @@
7378b84a
DM
252 .args_type = "",
253 .mhandler.cmd_new = qmp_marshal_input_query_target,
254 },
255+
256+ {
257+ .name = "snapshot-start",
5db17e8c 258+ .args_type = "statefile:s?",
7378b84a
DM
259+ .mhandler.cmd_new = qmp_marshal_input_snapshot_start,
260+ },
261+
262+ {
263+ .name = "snapshot-drive",
264+ .args_type = "device:s,name:s",
265+ .mhandler.cmd_new = qmp_marshal_input_snapshot_drive,
266+ },
267+
268+ {
71788d62
DM
269+ .name = "delete-drive-snapshot",
270+ .args_type = "device:s,name:s",
271+ .mhandler.cmd_new = qmp_marshal_input_delete_drive_snapshot,
272+ },
273+
274+ {
7378b84a
DM
275+ .name = "snapshot-end",
276+ .args_type = "",
277+ .mhandler.cmd_new = qmp_marshal_input_snapshot_end,
278+ },
279Index: new/hmp.c
280===================================================================
5db17e8c
DM
281--- new.orig/hmp.c 2012-09-07 07:41:45.000000000 +0200
282+++ new/hmp.c 2012-09-13 09:22:06.000000000 +0200
71788d62 283@@ -1102,3 +1102,40 @@
7378b84a
DM
284 qmp_closefd(fdname, &errp);
285 hmp_handle_error(mon, &errp);
286 }
287+
288+void hmp_snapshot_start(Monitor *mon, const QDict *qdict)
289+{
290+ Error *errp = NULL;
71788d62 291+ const char *statefile = qdict_get_try_str(qdict, "statefile");
7378b84a 292+
71788d62 293+ qmp_snapshot_start(statefile != NULL, statefile, &errp);
7378b84a
DM
294+ hmp_handle_error(mon, &errp);
295+}
296+
297+void hmp_snapshot_drive(Monitor *mon, const QDict *qdict)
298+{
299+ Error *errp = NULL;
300+ const char *name = qdict_get_str(qdict, "name");
301+ const char *device = qdict_get_str(qdict, "device");
302+
303+ qmp_snapshot_drive(device, name, &errp);
304+ hmp_handle_error(mon, &errp);
305+}
306+
71788d62
DM
307+void hmp_delete_drive_snapshot(Monitor *mon, const QDict *qdict)
308+{
309+ Error *errp = NULL;
310+ const char *name = qdict_get_str(qdict, "name");
311+ const char *device = qdict_get_str(qdict, "device");
312+
313+ qmp_delete_drive_snapshot(device, name, &errp);
314+ hmp_handle_error(mon, &errp);
315+}
316+
7378b84a
DM
317+void hmp_snapshot_end(Monitor *mon, const QDict *qdict)
318+{
319+ Error *errp = NULL;
320+
321+ qmp_snapshot_end(&errp);
322+ hmp_handle_error(mon, &errp);
323+}
324Index: new/hmp.h
325===================================================================
5db17e8c
DM
326--- new.orig/hmp.h 2012-09-07 07:41:45.000000000 +0200
327+++ new/hmp.h 2012-09-13 09:22:06.000000000 +0200
71788d62 328@@ -71,5 +71,9 @@
7378b84a
DM
329 void hmp_netdev_del(Monitor *mon, const QDict *qdict);
330 void hmp_getfd(Monitor *mon, const QDict *qdict);
331 void hmp_closefd(Monitor *mon, const QDict *qdict);
332+void hmp_snapshot_start(Monitor *mon, const QDict *qdict);
333+void hmp_snapshot_drive(Monitor *mon, const QDict *qdict);
71788d62 334+void hmp_delete_drive_snapshot(Monitor *mon, const QDict *qdict);
7378b84a
DM
335+void hmp_snapshot_end(Monitor *mon, const QDict *qdict);
336
337 #endif
338Index: new/hmp-commands.hx
339===================================================================
5db17e8c
DM
340--- new.orig/hmp-commands.hx 2012-09-07 07:41:45.000000000 +0200
341+++ new/hmp-commands.hx 2012-09-13 09:22:06.000000000 +0200
71788d62 342@@ -1494,3 +1494,35 @@
7378b84a
DM
343 STEXI
344 @end table
345 ETEXI
346+
347+ {
348+ .name = "snapshot-start",
71788d62
DM
349+ .args_type = "statefile:s?",
350+ .params = "[statefile]",
7378b84a
DM
351+ .help = "Prepare for snapshot and halt VM. Save VM state to statefile.",
352+ .mhandler.cmd = hmp_snapshot_start,
353+ },
354+
7378b84a
DM
355+ {
356+ .name = "snapshot-drive",
357+ .args_type = "device:s,name:s",
358+ .params = "device name",
359+ .help = "Create internal snapshot.",
360+ .mhandler.cmd = hmp_snapshot_drive,
361+ },
362+
363+ {
71788d62
DM
364+ .name = "delete-drive-snapshot",
365+ .args_type = "device:s,name:s",
366+ .params = "device name",
367+ .help = "Delete internal snapshot.",
368+ .mhandler.cmd = hmp_delete_drive_snapshot,
369+ },
370+
371+ {
7378b84a
DM
372+ .name = "snapshot-end",
373+ .args_type = "",
374+ .params = "",
375+ .help = "Resume VM after snaphot.",
376+ .mhandler.cmd = hmp_snapshot_end,
377+ },
e3a98889
DM
378Index: new/savevm.c
379===================================================================
5db17e8c 380--- new.orig/savevm.c 2012-09-07 07:41:45.000000000 +0200
49adae7d
DM
381+++ new/savevm.c 2012-09-14 11:32:17.000000000 +0200
382@@ -404,7 +404,7 @@
383 return bdrv_flush(opaque);
384 }
385
386-static QEMUFile *qemu_fopen_bdrv(BlockDriverState *bs, int is_writable)
387+QEMUFile *qemu_fopen_bdrv(BlockDriverState *bs, int is_writable)
388 {
389 if (is_writable)
390 return qemu_fopen_ops(bs, block_put_buffer, NULL, bdrv_fclose,
e3a98889
DM
391@@ -1724,7 +1724,7 @@
392 }
393 }
394
395-static int qemu_savevm_state(QEMUFile *f)
396+int qemu_savevm_state(QEMUFile *f)
397 {
398 int ret;
399 MigrationParams params = {
400Index: new/sysemu.h
401===================================================================
5db17e8c
DM
402--- new.orig/sysemu.h 2012-09-07 07:41:46.000000000 +0200
403+++ new/sysemu.h 2012-09-13 09:22:06.000000000 +0200
e3a98889
DM
404@@ -83,6 +83,7 @@
405 int qemu_savevm_state_iterate(QEMUFile *f);
406 int qemu_savevm_state_complete(QEMUFile *f);
407 void qemu_savevm_state_cancel(QEMUFile *f);
408+int qemu_savevm_state(QEMUFile *f);
409 int qemu_loadvm_state(QEMUFile *f);
410
411 /* SLIRP */
49adae7d
DM
412Index: new/qemu-file.h
413===================================================================
414--- new.orig/qemu-file.h 2012-09-14 11:51:31.000000000 +0200
415+++ new/qemu-file.h 2012-09-14 11:51:47.000000000 +0200
416@@ -68,6 +68,7 @@
417 QEMUFile *qemu_fopen(const char *filename, const char *mode);
418 QEMUFile *qemu_fdopen(int fd, const char *mode);
419 QEMUFile *qemu_fopen_socket(int fd);
420+QEMUFile *qemu_fopen_bdrv(BlockDriverState *bs, int is_writable);
421 QEMUFile *qemu_popen(FILE *popen_file, const char *mode);
422 QEMUFile *qemu_popen_cmd(const char *command, const char *mode);
423 int qemu_stdio_fd(QEMUFile *f);