]> git.proxmox.com Git - pve-qemu.git/blame - debian/patches/pve/0042-PVE-Use-coroutine-QMP-for-backup-cancel_backup.patch
savevm-async: avoid segfault when aborting snapshot
[pve-qemu.git] / debian / patches / pve / 0042-PVE-Use-coroutine-QMP-for-backup-cancel_backup.patch
CommitLineData
817b7667
SR
1From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2From: Stefan Reiter <s.reiter@proxmox.com>
3Date: Tue, 26 Jan 2021 15:45:30 +0100
4Subject: [PATCH] PVE: Use coroutine QMP for backup/cancel_backup
5
6Finally turn backup QMP calls into coroutines, now that it's possible.
7This has the benefit that calls are asynchronous to the main loop, i.e.
8long running operations like connecting to a PBS server will no longer
9hang the VM.
10
11Additionally, it allows us to get rid of block_on_coroutine_fn, which
12was always a hacky workaround.
13
14While we're already spring cleaning, also remove the QmpBackupTask
15struct, since we can now put the 'prepare' function directly into
16qmp_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
19required, otherwise monitor_get_fd() fails as we're not in a QMP
20coroutine, but one we start ourselves - we could of course set the
21monitor for that coroutine ourselves, but let's just fix it the right
22way instead)
23
24Signed-off-by: Stefan Reiter <s.reiter@proxmox.com>
ddbf7a87 25Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
817b7667
SR
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
34diff --git a/block/monitor/block-hmp-cmds.c b/block/monitor/block-hmp-cmds.c
dc9827a6 35index ea7b665aa2..ef45552e3b 100644
817b7667
SR
36--- a/block/monitor/block-hmp-cmds.c
37+++ b/block/monitor/block-hmp-cmds.c
f376b2b9 38@@ -1016,7 +1016,7 @@ void hmp_info_snapshots(Monitor *mon, const QDict *qdict)
817b7667
SR
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
f376b2b9 47@@ -1025,7 +1025,7 @@ void hmp_backup_cancel(Monitor *mon, const QDict *qdict)
817b7667
SR
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
56diff --git a/hmp-commands.hx b/hmp-commands.hx
dc9827a6 57index 994445f301..aaea875970 100644
817b7667
SR
58--- a/hmp-commands.hx
59+++ b/hmp-commands.hx
8dca018b 60@@ -109,6 +109,7 @@ ERST
817b7667
SR
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
8dca018b 68@@ -122,6 +123,7 @@ ERST
817b7667
SR
69 .params = "",
70 .help = "cancel the current VM backup",
71 .cmd = hmp_backup_cancel,
72+ .coroutine = true,
73 },
74
75 SRST
76diff --git a/proxmox-backup-client.c b/proxmox-backup-client.c
77index 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;
118diff --git a/pve-backup.c b/pve-backup.c
4567474e 119index 5fa3cc1352..323014744c 100644
817b7667
SR
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,
8dca018b 143@@ -533,50 +528,27 @@ static void create_backup_jobs_bh(void *opaque) {
817b7667
SR
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;
8dca018b 210@@ -593,17 +565,17 @@ static void coroutine_fn pvebackup_co_prepare(void *opaque)
817b7667
SR
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) {
8dca018b 233@@ -611,14 +583,14 @@ static void coroutine_fn pvebackup_co_prepare(void *opaque)
817b7667
SR
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 }
8dca018b 250@@ -641,7 +613,7 @@ static void coroutine_fn pvebackup_co_prepare(void *opaque)
817b7667
SR
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
8dca018b 259@@ -651,13 +623,13 @@ static void coroutine_fn pvebackup_co_prepare(void *opaque)
817b7667
SR
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;
8dca018b 275@@ -684,47 +656,44 @@ static void coroutine_fn pvebackup_co_prepare(void *opaque)
817b7667
SR
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
8dca018b 340@@ -743,9 +712,9 @@ static void coroutine_fn pvebackup_co_prepare(void *opaque)
817b7667
SR
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 }
8dca018b 352@@ -775,12 +744,12 @@ static void coroutine_fn pvebackup_co_prepare(void *opaque)
817b7667
SR
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
8dca018b 367@@ -794,10 +763,10 @@ static void coroutine_fn pvebackup_co_prepare(void *opaque)
817b7667
SR
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 }
8dca018b 380@@ -808,25 +777,25 @@ static void coroutine_fn pvebackup_co_prepare(void *opaque)
817b7667
SR
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) {
8dca018b 412@@ -840,34 +809,34 @@ static void coroutine_fn pvebackup_co_prepare(void *opaque)
817b7667
SR
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 }
8dca018b 456@@ -885,7 +854,7 @@ static void coroutine_fn pvebackup_co_prepare(void *opaque)
817b7667
SR
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);
8dca018b 465@@ -900,7 +869,7 @@ static void coroutine_fn pvebackup_co_prepare(void *opaque)
817b7667
SR
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;
8dca018b 474@@ -910,8 +879,6 @@ static void coroutine_fn pvebackup_co_prepare(void *opaque)
817b7667
SR
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.
8dca018b 483@@ -925,7 +892,7 @@ static void coroutine_fn pvebackup_co_prepare(void *opaque)
817b7667
SR
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
8dca018b 492@@ -938,7 +905,7 @@ static void coroutine_fn pvebackup_co_prepare(void *opaque)
817b7667
SR
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);
8dca018b 501@@ -969,7 +936,7 @@ err:
817b7667
SR
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) {
8dca018b 510@@ -980,65 +947,8 @@ err:
817b7667
SR
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)
577diff --git a/qapi/block-core.json b/qapi/block-core.json
dc9827a6 578index 05382a1069..f0399bf249 100644
817b7667
SR
579--- a/qapi/block-core.json
580+++ b/qapi/block-core.json
4567474e 581@@ -846,7 +846,7 @@
817b7667
SR
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:
4567474e 590@@ -868,7 +868,7 @@
817b7667
SR
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: