]> git.proxmox.com Git - pve-qemu.git/blob - debian/patches/pve/0048-PVE-Use-coroutine-QMP-for-backup-cancel_backup.patch
clean up pve/ patches by squashing patches of patches
[pve-qemu.git] / debian / patches / pve / 0048-PVE-Use-coroutine-QMP-for-backup-cancel_backup.patch
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: