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