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