]>
Commit | Line | Data |
---|---|---|
817b7667 SR |
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |
2 | From: Stefan Reiter <s.reiter@proxmox.com> | |
3 | Date: Tue, 26 Jan 2021 15:45:30 +0100 | |
4 | Subject: [PATCH] PVE: Use coroutine QMP for backup/cancel_backup | |
5 | ||
6 | Finally turn backup QMP calls into coroutines, now that it's possible. | |
7 | This has the benefit that calls are asynchronous to the main loop, i.e. | |
8 | long running operations like connecting to a PBS server will no longer | |
9 | hang the VM. | |
10 | ||
11 | Additionally, it allows us to get rid of block_on_coroutine_fn, which | |
12 | was always a hacky workaround. | |
13 | ||
14 | While we're already spring cleaning, also remove the QmpBackupTask | |
15 | struct, since we can now put the 'prepare' function directly into | |
16 | qmp_backup and thus no longer need those giant walls of text. | |
17 | ||
18 | (Note that for our patches to work with 5.2.0 this change is actually | |
19 | required, otherwise monitor_get_fd() fails as we're not in a QMP | |
20 | coroutine, but one we start ourselves - we could of course set the | |
21 | monitor for that coroutine ourselves, but let's just fix it the right | |
22 | way instead) | |
23 | ||
24 | Signed-off-by: Stefan Reiter <s.reiter@proxmox.com> | |
25 | --- | |
26 | block/monitor/block-hmp-cmds.c | 4 +- | |
27 | hmp-commands.hx | 2 + | |
28 | proxmox-backup-client.c | 31 ----- | |
29 | pve-backup.c | 232 ++++++++++----------------------- | |
30 | qapi/block-core.json | 4 +- | |
31 | 5 files changed, 77 insertions(+), 196 deletions(-) | |
32 | ||
33 | diff --git a/block/monitor/block-hmp-cmds.c b/block/monitor/block-hmp-cmds.c | |
34 | index 46c63b1cf9..11c84d5508 100644 | |
35 | --- a/block/monitor/block-hmp-cmds.c | |
36 | +++ b/block/monitor/block-hmp-cmds.c | |
37 | @@ -1013,7 +1013,7 @@ void hmp_info_snapshots(Monitor *mon, const QDict *qdict) | |
38 | g_free(global_snapshots); | |
39 | } | |
40 | ||
41 | -void hmp_backup_cancel(Monitor *mon, const QDict *qdict) | |
42 | +void coroutine_fn hmp_backup_cancel(Monitor *mon, const QDict *qdict) | |
43 | { | |
44 | Error *error = NULL; | |
45 | ||
46 | @@ -1022,7 +1022,7 @@ void hmp_backup_cancel(Monitor *mon, const QDict *qdict) | |
47 | hmp_handle_error(mon, error); | |
48 | } | |
49 | ||
50 | -void hmp_backup(Monitor *mon, const QDict *qdict) | |
51 | +void coroutine_fn hmp_backup(Monitor *mon, const QDict *qdict) | |
52 | { | |
53 | Error *error = NULL; | |
54 | ||
55 | diff --git a/hmp-commands.hx b/hmp-commands.hx | |
56 | index 0c6b944850..54de3f80e6 100644 | |
57 | --- a/hmp-commands.hx | |
58 | +++ b/hmp-commands.hx | |
59 | @@ -108,6 +108,7 @@ ERST | |
60 | "\n\t\t\t Use -d to dump data into a directory instead" | |
61 | "\n\t\t\t of using VMA format.", | |
62 | .cmd = hmp_backup, | |
63 | + .coroutine = true, | |
64 | }, | |
65 | ||
66 | SRST | |
67 | @@ -121,6 +122,7 @@ ERST | |
68 | .params = "", | |
69 | .help = "cancel the current VM backup", | |
70 | .cmd = hmp_backup_cancel, | |
71 | + .coroutine = true, | |
72 | }, | |
73 | ||
74 | SRST | |
75 | diff --git a/proxmox-backup-client.c b/proxmox-backup-client.c | |
76 | index 4ce7bc0b5e..0923037dec 100644 | |
77 | --- a/proxmox-backup-client.c | |
78 | +++ b/proxmox-backup-client.c | |
79 | @@ -5,37 +5,6 @@ | |
80 | ||
81 | /* Proxmox Backup Server client bindings using coroutines */ | |
82 | ||
83 | -typedef struct BlockOnCoroutineWrapper { | |
84 | - AioContext *ctx; | |
85 | - CoroutineEntry *entry; | |
86 | - void *entry_arg; | |
87 | - bool finished; | |
88 | -} BlockOnCoroutineWrapper; | |
89 | - | |
90 | -static void coroutine_fn block_on_coroutine_wrapper(void *opaque) | |
91 | -{ | |
92 | - BlockOnCoroutineWrapper *wrapper = opaque; | |
93 | - wrapper->entry(wrapper->entry_arg); | |
94 | - wrapper->finished = true; | |
95 | - aio_wait_kick(); | |
96 | -} | |
97 | - | |
98 | -void block_on_coroutine_fn(CoroutineEntry *entry, void *entry_arg) | |
99 | -{ | |
100 | - assert(!qemu_in_coroutine()); | |
101 | - | |
102 | - AioContext *ctx = qemu_get_current_aio_context(); | |
103 | - BlockOnCoroutineWrapper wrapper = { | |
104 | - .finished = false, | |
105 | - .entry = entry, | |
106 | - .entry_arg = entry_arg, | |
107 | - .ctx = ctx, | |
108 | - }; | |
109 | - Coroutine *wrapper_co = qemu_coroutine_create(block_on_coroutine_wrapper, &wrapper); | |
110 | - aio_co_enter(ctx, wrapper_co); | |
111 | - AIO_WAIT_WHILE(ctx, !wrapper.finished); | |
112 | -} | |
113 | - | |
114 | // This is called from another thread, so we use aio_co_schedule() | |
115 | static void proxmox_backup_schedule_wake(void *data) { | |
116 | CoCtxData *waker = (CoCtxData *)data; | |
117 | diff --git a/pve-backup.c b/pve-backup.c | |
118 | index 6b25292ba1..f7597ae55c 100644 | |
119 | --- a/pve-backup.c | |
120 | +++ b/pve-backup.c | |
121 | @@ -357,7 +357,7 @@ static void job_cancel_bh(void *opaque) { | |
122 | aio_co_enter(data->ctx, data->co); | |
123 | } | |
124 | ||
125 | -static void coroutine_fn pvebackup_co_cancel(void *opaque) | |
126 | +void coroutine_fn qmp_backup_cancel(Error **errp) | |
127 | { | |
128 | Error *cancel_err = NULL; | |
129 | error_setg(&cancel_err, "backup canceled"); | |
130 | @@ -394,11 +394,6 @@ static void coroutine_fn pvebackup_co_cancel(void *opaque) | |
131 | qemu_co_mutex_unlock(&backup_state.backup_mutex); | |
132 | } | |
133 | ||
134 | -void qmp_backup_cancel(Error **errp) | |
135 | -{ | |
136 | - block_on_coroutine_fn(pvebackup_co_cancel, NULL); | |
137 | -} | |
138 | - | |
139 | // assumes the caller holds backup_mutex | |
140 | static int coroutine_fn pvebackup_co_add_config( | |
141 | const char *file, | |
142 | @@ -531,50 +526,27 @@ static void create_backup_jobs_bh(void *opaque) { | |
143 | aio_co_enter(data->ctx, data->co); | |
144 | } | |
145 | ||
146 | -typedef struct QmpBackupTask { | |
147 | - const char *backup_file; | |
148 | - bool has_password; | |
149 | - const char *password; | |
150 | - bool has_keyfile; | |
151 | - const char *keyfile; | |
152 | - bool has_key_password; | |
153 | - const char *key_password; | |
154 | - bool has_backup_id; | |
155 | - const char *backup_id; | |
156 | - bool has_backup_time; | |
157 | - const char *fingerprint; | |
158 | - bool has_fingerprint; | |
159 | - int64_t backup_time; | |
160 | - bool has_use_dirty_bitmap; | |
161 | - bool use_dirty_bitmap; | |
162 | - bool has_format; | |
163 | - BackupFormat format; | |
164 | - bool has_config_file; | |
165 | - const char *config_file; | |
166 | - bool has_firewall_file; | |
167 | - const char *firewall_file; | |
168 | - bool has_devlist; | |
169 | - const char *devlist; | |
170 | - bool has_compress; | |
171 | - bool compress; | |
172 | - bool has_encrypt; | |
173 | - bool encrypt; | |
174 | - bool has_speed; | |
175 | - int64_t speed; | |
176 | - Error **errp; | |
177 | - UuidInfo *result; | |
178 | -} QmpBackupTask; | |
179 | - | |
180 | -static void coroutine_fn pvebackup_co_prepare(void *opaque) | |
181 | +UuidInfo coroutine_fn *qmp_backup( | |
182 | + const char *backup_file, | |
183 | + bool has_password, const char *password, | |
184 | + bool has_keyfile, const char *keyfile, | |
185 | + bool has_key_password, const char *key_password, | |
186 | + bool has_fingerprint, const char *fingerprint, | |
187 | + bool has_backup_id, const char *backup_id, | |
188 | + bool has_backup_time, int64_t backup_time, | |
189 | + bool has_use_dirty_bitmap, bool use_dirty_bitmap, | |
190 | + bool has_compress, bool compress, | |
191 | + bool has_encrypt, bool encrypt, | |
192 | + bool has_format, BackupFormat format, | |
193 | + bool has_config_file, const char *config_file, | |
194 | + bool has_firewall_file, const char *firewall_file, | |
195 | + bool has_devlist, const char *devlist, | |
196 | + bool has_speed, int64_t speed, Error **errp) | |
197 | { | |
198 | assert(qemu_in_coroutine()); | |
199 | ||
200 | qemu_co_mutex_lock(&backup_state.backup_mutex); | |
201 | ||
202 | - QmpBackupTask *task = opaque; | |
203 | - | |
204 | - task->result = NULL; // just to be sure | |
205 | - | |
206 | BlockBackend *blk; | |
207 | BlockDriverState *bs = NULL; | |
208 | const char *backup_dir = NULL; | |
209 | @@ -591,17 +563,17 @@ static void coroutine_fn pvebackup_co_prepare(void *opaque) | |
210 | const char *firewall_name = "qemu-server.fw"; | |
211 | ||
212 | if (backup_state.di_list) { | |
213 | - error_set(task->errp, ERROR_CLASS_GENERIC_ERROR, | |
214 | + error_set(errp, ERROR_CLASS_GENERIC_ERROR, | |
215 | "previous backup not finished"); | |
216 | qemu_co_mutex_unlock(&backup_state.backup_mutex); | |
217 | - return; | |
218 | + return NULL; | |
219 | } | |
220 | ||
221 | /* Todo: try to auto-detect format based on file name */ | |
222 | - BackupFormat format = task->has_format ? task->format : BACKUP_FORMAT_VMA; | |
223 | + format = has_format ? format : BACKUP_FORMAT_VMA; | |
224 | ||
225 | - if (task->has_devlist) { | |
226 | - devs = g_strsplit_set(task->devlist, ",;:", -1); | |
227 | + if (has_devlist) { | |
228 | + devs = g_strsplit_set(devlist, ",;:", -1); | |
229 | ||
230 | gchar **d = devs; | |
231 | while (d && *d) { | |
232 | @@ -609,14 +581,14 @@ static void coroutine_fn pvebackup_co_prepare(void *opaque) | |
233 | if (blk) { | |
234 | bs = blk_bs(blk); | |
235 | if (!bdrv_is_inserted(bs)) { | |
236 | - error_setg(task->errp, QERR_DEVICE_HAS_NO_MEDIUM, *d); | |
237 | + error_setg(errp, QERR_DEVICE_HAS_NO_MEDIUM, *d); | |
238 | goto err; | |
239 | } | |
240 | PVEBackupDevInfo *di = g_new0(PVEBackupDevInfo, 1); | |
241 | di->bs = bs; | |
242 | di_list = g_list_append(di_list, di); | |
243 | } else { | |
244 | - error_set(task->errp, ERROR_CLASS_DEVICE_NOT_FOUND, | |
245 | + error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND, | |
246 | "Device '%s' not found", *d); | |
247 | goto err; | |
248 | } | |
249 | @@ -639,7 +611,7 @@ static void coroutine_fn pvebackup_co_prepare(void *opaque) | |
250 | } | |
251 | ||
252 | if (!di_list) { | |
253 | - error_set(task->errp, ERROR_CLASS_GENERIC_ERROR, "empty device list"); | |
254 | + error_set(errp, ERROR_CLASS_GENERIC_ERROR, "empty device list"); | |
255 | goto err; | |
256 | } | |
257 | ||
258 | @@ -649,13 +621,13 @@ static void coroutine_fn pvebackup_co_prepare(void *opaque) | |
259 | while (l) { | |
260 | PVEBackupDevInfo *di = (PVEBackupDevInfo *)l->data; | |
261 | l = g_list_next(l); | |
262 | - if (bdrv_op_is_blocked(di->bs, BLOCK_OP_TYPE_BACKUP_SOURCE, task->errp)) { | |
263 | + if (bdrv_op_is_blocked(di->bs, BLOCK_OP_TYPE_BACKUP_SOURCE, errp)) { | |
264 | goto err; | |
265 | } | |
266 | ||
267 | ssize_t size = bdrv_getlength(di->bs); | |
268 | if (size < 0) { | |
269 | - error_setg_errno(task->errp, -di->size, "bdrv_getlength failed"); | |
270 | + error_setg_errno(errp, -di->size, "bdrv_getlength failed"); | |
271 | goto err; | |
272 | } | |
273 | di->size = size; | |
274 | @@ -682,47 +654,44 @@ static void coroutine_fn pvebackup_co_prepare(void *opaque) | |
275 | } | |
276 | ||
277 | if (format == BACKUP_FORMAT_PBS) { | |
278 | - if (!task->has_password) { | |
279 | - error_set(task->errp, ERROR_CLASS_GENERIC_ERROR, "missing parameter 'password'"); | |
280 | + if (!has_password) { | |
281 | + error_set(errp, ERROR_CLASS_GENERIC_ERROR, "missing parameter 'password'"); | |
282 | goto err_mutex; | |
283 | } | |
284 | - if (!task->has_backup_id) { | |
285 | - error_set(task->errp, ERROR_CLASS_GENERIC_ERROR, "missing parameter 'backup-id'"); | |
286 | + if (!has_backup_id) { | |
287 | + error_set(errp, ERROR_CLASS_GENERIC_ERROR, "missing parameter 'backup-id'"); | |
288 | goto err_mutex; | |
289 | } | |
290 | - if (!task->has_backup_time) { | |
291 | - error_set(task->errp, ERROR_CLASS_GENERIC_ERROR, "missing parameter 'backup-time'"); | |
292 | + if (!has_backup_time) { | |
293 | + error_set(errp, ERROR_CLASS_GENERIC_ERROR, "missing parameter 'backup-time'"); | |
294 | goto err_mutex; | |
295 | } | |
296 | ||
297 | int dump_cb_block_size = PROXMOX_BACKUP_DEFAULT_CHUNK_SIZE; // Hardcoded (4M) | |
298 | firewall_name = "fw.conf"; | |
299 | ||
300 | - bool use_dirty_bitmap = task->has_use_dirty_bitmap && task->use_dirty_bitmap; | |
301 | - | |
302 | - | |
303 | char *pbs_err = NULL; | |
304 | pbs = proxmox_backup_new( | |
305 | - task->backup_file, | |
306 | - task->backup_id, | |
307 | - task->backup_time, | |
308 | + backup_file, | |
309 | + backup_id, | |
310 | + backup_time, | |
311 | dump_cb_block_size, | |
312 | - task->has_password ? task->password : NULL, | |
313 | - task->has_keyfile ? task->keyfile : NULL, | |
314 | - task->has_key_password ? task->key_password : NULL, | |
315 | - task->has_compress ? task->compress : true, | |
316 | - task->has_encrypt ? task->encrypt : task->has_keyfile, | |
317 | - task->has_fingerprint ? task->fingerprint : NULL, | |
318 | + has_password ? password : NULL, | |
319 | + has_keyfile ? keyfile : NULL, | |
320 | + has_key_password ? key_password : NULL, | |
321 | + has_compress ? compress : true, | |
322 | + has_encrypt ? encrypt : has_keyfile, | |
323 | + has_fingerprint ? fingerprint : NULL, | |
324 | &pbs_err); | |
325 | ||
326 | if (!pbs) { | |
327 | - error_set(task->errp, ERROR_CLASS_GENERIC_ERROR, | |
328 | + error_set(errp, ERROR_CLASS_GENERIC_ERROR, | |
329 | "proxmox_backup_new failed: %s", pbs_err); | |
330 | proxmox_backup_free_error(pbs_err); | |
331 | goto err_mutex; | |
332 | } | |
333 | ||
334 | - int connect_result = proxmox_backup_co_connect(pbs, task->errp); | |
335 | + int connect_result = proxmox_backup_co_connect(pbs, errp); | |
336 | if (connect_result < 0) | |
337 | goto err_mutex; | |
338 | ||
339 | @@ -741,9 +710,9 @@ static void coroutine_fn pvebackup_co_prepare(void *opaque) | |
340 | BdrvDirtyBitmap *bitmap = bdrv_find_dirty_bitmap(di->bs, PBS_BITMAP_NAME); | |
341 | bool expect_only_dirty = false; | |
342 | ||
343 | - if (use_dirty_bitmap) { | |
344 | + if (has_use_dirty_bitmap && use_dirty_bitmap) { | |
345 | if (bitmap == NULL) { | |
346 | - bitmap = bdrv_create_dirty_bitmap(di->bs, dump_cb_block_size, PBS_BITMAP_NAME, task->errp); | |
347 | + bitmap = bdrv_create_dirty_bitmap(di->bs, dump_cb_block_size, PBS_BITMAP_NAME, errp); | |
348 | if (!bitmap) { | |
349 | goto err_mutex; | |
350 | } | |
351 | @@ -773,12 +742,12 @@ static void coroutine_fn pvebackup_co_prepare(void *opaque) | |
352 | } | |
353 | } | |
354 | ||
355 | - int dev_id = proxmox_backup_co_register_image(pbs, devname, di->size, expect_only_dirty, task->errp); | |
356 | + int dev_id = proxmox_backup_co_register_image(pbs, devname, di->size, expect_only_dirty, errp); | |
357 | if (dev_id < 0) { | |
358 | goto err_mutex; | |
359 | } | |
360 | ||
361 | - if (!(di->target = bdrv_backup_dump_create(dump_cb_block_size, di->size, pvebackup_co_dump_pbs_cb, di, task->errp))) { | |
362 | + if (!(di->target = bdrv_backup_dump_create(dump_cb_block_size, di->size, pvebackup_co_dump_pbs_cb, di, errp))) { | |
363 | goto err_mutex; | |
364 | } | |
365 | ||
366 | @@ -792,10 +761,10 @@ static void coroutine_fn pvebackup_co_prepare(void *opaque) | |
367 | backup_state.stat.bitmap_list = g_list_append(backup_state.stat.bitmap_list, info); | |
368 | } | |
369 | } else if (format == BACKUP_FORMAT_VMA) { | |
370 | - vmaw = vma_writer_create(task->backup_file, uuid, &local_err); | |
371 | + vmaw = vma_writer_create(backup_file, uuid, &local_err); | |
372 | if (!vmaw) { | |
373 | if (local_err) { | |
374 | - error_propagate(task->errp, local_err); | |
375 | + error_propagate(errp, local_err); | |
376 | } | |
377 | goto err_mutex; | |
378 | } | |
379 | @@ -806,25 +775,25 @@ static void coroutine_fn pvebackup_co_prepare(void *opaque) | |
380 | PVEBackupDevInfo *di = (PVEBackupDevInfo *)l->data; | |
381 | l = g_list_next(l); | |
382 | ||
383 | - if (!(di->target = bdrv_backup_dump_create(VMA_CLUSTER_SIZE, di->size, pvebackup_co_dump_vma_cb, di, task->errp))) { | |
384 | + if (!(di->target = bdrv_backup_dump_create(VMA_CLUSTER_SIZE, di->size, pvebackup_co_dump_vma_cb, di, errp))) { | |
385 | goto err_mutex; | |
386 | } | |
387 | ||
388 | const char *devname = bdrv_get_device_name(di->bs); | |
389 | di->dev_id = vma_writer_register_stream(vmaw, devname, di->size); | |
390 | if (di->dev_id <= 0) { | |
391 | - error_set(task->errp, ERROR_CLASS_GENERIC_ERROR, | |
392 | + error_set(errp, ERROR_CLASS_GENERIC_ERROR, | |
393 | "register_stream failed"); | |
394 | goto err_mutex; | |
395 | } | |
396 | } | |
397 | } else if (format == BACKUP_FORMAT_DIR) { | |
398 | - if (mkdir(task->backup_file, 0640) != 0) { | |
399 | - error_setg_errno(task->errp, errno, "can't create directory '%s'\n", | |
400 | - task->backup_file); | |
401 | + if (mkdir(backup_file, 0640) != 0) { | |
402 | + error_setg_errno(errp, errno, "can't create directory '%s'\n", | |
403 | + backup_file); | |
404 | goto err_mutex; | |
405 | } | |
406 | - backup_dir = task->backup_file; | |
407 | + backup_dir = backup_file; | |
408 | ||
409 | l = di_list; | |
410 | while (l) { | |
411 | @@ -838,34 +807,34 @@ static void coroutine_fn pvebackup_co_prepare(void *opaque) | |
412 | bdrv_img_create(di->targetfile, "raw", NULL, NULL, NULL, | |
413 | di->size, flags, false, &local_err); | |
414 | if (local_err) { | |
415 | - error_propagate(task->errp, local_err); | |
416 | + error_propagate(errp, local_err); | |
417 | goto err_mutex; | |
418 | } | |
419 | ||
420 | di->target = bdrv_open(di->targetfile, NULL, NULL, flags, &local_err); | |
421 | if (!di->target) { | |
422 | - error_propagate(task->errp, local_err); | |
423 | + error_propagate(errp, local_err); | |
424 | goto err_mutex; | |
425 | } | |
426 | } | |
427 | } else { | |
428 | - error_set(task->errp, ERROR_CLASS_GENERIC_ERROR, "unknown backup format"); | |
429 | + error_set(errp, ERROR_CLASS_GENERIC_ERROR, "unknown backup format"); | |
430 | goto err_mutex; | |
431 | } | |
432 | ||
433 | ||
434 | /* add configuration file to archive */ | |
435 | - if (task->has_config_file) { | |
436 | - if (pvebackup_co_add_config(task->config_file, config_name, format, backup_dir, | |
437 | - vmaw, pbs, task->errp) != 0) { | |
438 | + if (has_config_file) { | |
439 | + if (pvebackup_co_add_config(config_file, config_name, format, backup_dir, | |
440 | + vmaw, pbs, errp) != 0) { | |
441 | goto err_mutex; | |
442 | } | |
443 | } | |
444 | ||
445 | /* add firewall file to archive */ | |
446 | - if (task->has_firewall_file) { | |
447 | - if (pvebackup_co_add_config(task->firewall_file, firewall_name, format, backup_dir, | |
448 | - vmaw, pbs, task->errp) != 0) { | |
449 | + if (has_firewall_file) { | |
450 | + if (pvebackup_co_add_config(firewall_file, firewall_name, format, backup_dir, | |
451 | + vmaw, pbs, errp) != 0) { | |
452 | goto err_mutex; | |
453 | } | |
454 | } | |
455 | @@ -883,7 +852,7 @@ static void coroutine_fn pvebackup_co_prepare(void *opaque) | |
456 | if (backup_state.stat.backup_file) { | |
457 | g_free(backup_state.stat.backup_file); | |
458 | } | |
459 | - backup_state.stat.backup_file = g_strdup(task->backup_file); | |
460 | + backup_state.stat.backup_file = g_strdup(backup_file); | |
461 | ||
462 | uuid_copy(backup_state.stat.uuid, uuid); | |
463 | uuid_unparse_lower(uuid, backup_state.stat.uuid_str); | |
464 | @@ -898,7 +867,7 @@ static void coroutine_fn pvebackup_co_prepare(void *opaque) | |
465 | ||
466 | qemu_mutex_unlock(&backup_state.stat.lock); | |
467 | ||
468 | - backup_state.speed = (task->has_speed && task->speed > 0) ? task->speed : 0; | |
469 | + backup_state.speed = (has_speed && speed > 0) ? speed : 0; | |
470 | ||
471 | backup_state.vmaw = vmaw; | |
472 | backup_state.pbs = pbs; | |
473 | @@ -908,8 +877,6 @@ static void coroutine_fn pvebackup_co_prepare(void *opaque) | |
474 | uuid_info = g_malloc0(sizeof(*uuid_info)); | |
475 | uuid_info->UUID = uuid_str; | |
476 | ||
477 | - task->result = uuid_info; | |
478 | - | |
479 | /* Run create_backup_jobs_bh outside of coroutine (in BH) but keep | |
480 | * backup_mutex locked. This is fine, a CoMutex can be held across yield | |
481 | * points, and we'll release it as soon as the BH reschedules us. | |
482 | @@ -923,7 +890,7 @@ static void coroutine_fn pvebackup_co_prepare(void *opaque) | |
483 | qemu_coroutine_yield(); | |
484 | ||
485 | if (local_err) { | |
486 | - error_propagate(task->errp, local_err); | |
487 | + error_propagate(errp, local_err); | |
488 | goto err; | |
489 | } | |
490 | ||
491 | @@ -936,7 +903,7 @@ static void coroutine_fn pvebackup_co_prepare(void *opaque) | |
492 | /* start the first job in the transaction */ | |
493 | job_txn_start_seq(backup_state.txn); | |
494 | ||
495 | - return; | |
496 | + return uuid_info; | |
497 | ||
498 | err_mutex: | |
499 | qemu_mutex_unlock(&backup_state.stat.lock); | |
500 | @@ -967,7 +934,7 @@ err: | |
501 | if (vmaw) { | |
502 | Error *err = NULL; | |
503 | vma_writer_close(vmaw, &err); | |
504 | - unlink(task->backup_file); | |
505 | + unlink(backup_file); | |
506 | } | |
507 | ||
508 | if (pbs) { | |
509 | @@ -978,65 +945,8 @@ err: | |
510 | rmdir(backup_dir); | |
511 | } | |
512 | ||
513 | - task->result = NULL; | |
514 | - | |
515 | qemu_co_mutex_unlock(&backup_state.backup_mutex); | |
516 | - return; | |
517 | -} | |
518 | - | |
519 | -UuidInfo *qmp_backup( | |
520 | - const char *backup_file, | |
521 | - bool has_password, const char *password, | |
522 | - bool has_keyfile, const char *keyfile, | |
523 | - bool has_key_password, const char *key_password, | |
524 | - bool has_fingerprint, const char *fingerprint, | |
525 | - bool has_backup_id, const char *backup_id, | |
526 | - bool has_backup_time, int64_t backup_time, | |
527 | - bool has_use_dirty_bitmap, bool use_dirty_bitmap, | |
528 | - bool has_compress, bool compress, | |
529 | - bool has_encrypt, bool encrypt, | |
530 | - bool has_format, BackupFormat format, | |
531 | - bool has_config_file, const char *config_file, | |
532 | - bool has_firewall_file, const char *firewall_file, | |
533 | - bool has_devlist, const char *devlist, | |
534 | - bool has_speed, int64_t speed, Error **errp) | |
535 | -{ | |
536 | - QmpBackupTask task = { | |
537 | - .backup_file = backup_file, | |
538 | - .has_password = has_password, | |
539 | - .password = password, | |
540 | - .has_keyfile = has_keyfile, | |
541 | - .keyfile = keyfile, | |
542 | - .has_key_password = has_key_password, | |
543 | - .key_password = key_password, | |
544 | - .has_fingerprint = has_fingerprint, | |
545 | - .fingerprint = fingerprint, | |
546 | - .has_backup_id = has_backup_id, | |
547 | - .backup_id = backup_id, | |
548 | - .has_backup_time = has_backup_time, | |
549 | - .backup_time = backup_time, | |
550 | - .has_use_dirty_bitmap = has_use_dirty_bitmap, | |
551 | - .use_dirty_bitmap = use_dirty_bitmap, | |
552 | - .has_compress = has_compress, | |
553 | - .compress = compress, | |
554 | - .has_encrypt = has_encrypt, | |
555 | - .encrypt = encrypt, | |
556 | - .has_format = has_format, | |
557 | - .format = format, | |
558 | - .has_config_file = has_config_file, | |
559 | - .config_file = config_file, | |
560 | - .has_firewall_file = has_firewall_file, | |
561 | - .firewall_file = firewall_file, | |
562 | - .has_devlist = has_devlist, | |
563 | - .devlist = devlist, | |
564 | - .has_speed = has_speed, | |
565 | - .speed = speed, | |
566 | - .errp = errp, | |
567 | - }; | |
568 | - | |
569 | - block_on_coroutine_fn(pvebackup_co_prepare, &task); | |
570 | - | |
571 | - return task.result; | |
572 | + return NULL; | |
573 | } | |
574 | ||
575 | BackupStatus *qmp_query_backup(Error **errp) | |
576 | diff --git a/qapi/block-core.json b/qapi/block-core.json | |
577 | index dee3d87efe..82133e2bee 100644 | |
578 | --- a/qapi/block-core.json | |
579 | +++ b/qapi/block-core.json | |
580 | @@ -847,7 +847,7 @@ | |
581 | '*config-file': 'str', | |
582 | '*firewall-file': 'str', | |
583 | '*devlist': 'str', '*speed': 'int' }, | |
584 | - 'returns': 'UuidInfo' } | |
585 | + 'returns': 'UuidInfo', 'coroutine': true } | |
586 | ||
587 | ## | |
588 | # @query-backup: | |
589 | @@ -869,7 +869,7 @@ | |
590 | # Notes: This command succeeds even if there is no backup process running. | |
591 | # | |
592 | ## | |
593 | -{ 'command': 'backup-cancel' } | |
594 | +{ 'command': 'backup-cancel', 'coroutine': true } | |
595 | ||
596 | ## | |
597 | # @ProxmoxSupportStatus: |