]> git.proxmox.com Git - pve-qemu-kvm.git/blob - debian/patches/internal-snapshot.patch
bf1fdf678d48a52dc74f96723315197c9f8af76d
[pve-qemu-kvm.git] / debian / patches / internal-snapshot.patch
1 Index: new/qapi-schema.json
2 ===================================================================
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
5 @@ -2493,3 +2493,12 @@
6 # Since: 1.2.0
7 ##
8 { 'command': 'query-target', 'returns': 'TargetInfo' }
9 +
10 +
11 +{ 'command': 'snapshot-start' 'data': { '*statefile': 'str' } }
12 +
13 +{ 'command': 'snapshot-drive', 'data': { 'device': 'str', 'name': 'str' } }
14 +
15 +{ 'command': 'delete-drive-snapshot', 'data': { 'device': 'str', 'name': 'str' } }
16 +
17 +{ 'command': 'snapshot-end' }
18 Index: new/qmp.c
19 ===================================================================
20 --- new.orig/qmp.c 2012-09-07 07:41:45.000000000 +0200
21 +++ new/qmp.c 2012-09-13 09:22:06.000000000 +0200
22 @@ -479,3 +479,191 @@
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 +
31 +void qmp_snapshot_start(bool has_statefile, const char *statefile, Error **errp)
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 + }
41 +
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 +
48 + if (!has_statefile)
49 + return;
50 +
51 + f = qemu_fopen(statefile, "wb");
52 + if (!f) {
53 + error_set(errp, QERR_OPEN_FILE_FAILED, statefile);
54 + goto restart;
55 + }
56 +
57 + ret = qemu_savevm_state(f);
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);
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();
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 +}
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 +}
214 Index: new/qmp-commands.hx
215 ===================================================================
216 --- new.orig/qmp-commands.hx 2012-09-07 07:41:45.000000000 +0200
217 +++ new/qmp-commands.hx 2012-09-13 09:30:33.000000000 +0200
218 @@ -2514,3 +2514,27 @@
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 + {
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 + {
242 + .name = "snapshot-end",
243 + .args_type = "",
244 + .mhandler.cmd_new = qmp_marshal_input_snapshot_end,
245 + },
246 Index: new/hmp.c
247 ===================================================================
248 --- new.orig/hmp.c 2012-09-07 07:41:45.000000000 +0200
249 +++ new/hmp.c 2012-09-13 09:22:06.000000000 +0200
250 @@ -1102,3 +1102,40 @@
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;
258 + const char *statefile = qdict_get_try_str(qdict, "statefile");
259 +
260 + qmp_snapshot_start(statefile != NULL, statefile, &errp);
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 +
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 +
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 +}
291 Index: new/hmp.h
292 ===================================================================
293 --- new.orig/hmp.h 2012-09-07 07:41:45.000000000 +0200
294 +++ new/hmp.h 2012-09-13 09:22:06.000000000 +0200
295 @@ -71,5 +71,9 @@
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);
301 +void hmp_delete_drive_snapshot(Monitor *mon, const QDict *qdict);
302 +void hmp_snapshot_end(Monitor *mon, const QDict *qdict);
303
304 #endif
305 Index: new/hmp-commands.hx
306 ===================================================================
307 --- new.orig/hmp-commands.hx 2012-09-07 07:41:45.000000000 +0200
308 +++ new/hmp-commands.hx 2012-09-13 09:22:06.000000000 +0200
309 @@ -1494,3 +1494,35 @@
310 STEXI
311 @end table
312 ETEXI
313 +
314 + {
315 + .name = "snapshot-start",
316 + .args_type = "statefile:s?",
317 + .params = "[statefile]",
318 + .help = "Prepare for snapshot and halt VM. Save VM state to statefile.",
319 + .mhandler.cmd = hmp_snapshot_start,
320 + },
321 +
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 + {
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 + {
339 + .name = "snapshot-end",
340 + .args_type = "",
341 + .params = "",
342 + .help = "Resume VM after snaphot.",
343 + .mhandler.cmd = hmp_snapshot_end,
344 + },
345 Index: new/savevm.c
346 ===================================================================
347 --- new.orig/savevm.c 2012-09-07 07:41:45.000000000 +0200
348 +++ new/savevm.c 2012-09-13 09:22:06.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 = {
358 Index: new/sysemu.h
359 ===================================================================
360 --- new.orig/sysemu.h 2012-09-07 07:41:46.000000000 +0200
361 +++ new/sysemu.h 2012-09-13 09:22:06.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 */