]>
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> | |
ddbf7a87 | 25 | Signed-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 | ||
34 | diff --git a/block/monitor/block-hmp-cmds.c b/block/monitor/block-hmp-cmds.c | |
dc9827a6 | 35 | index 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 | ||
56 | diff --git a/hmp-commands.hx b/hmp-commands.hx | |
dc9827a6 | 57 | index 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 | |
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 | |
4567474e | 119 | index 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) | |
577 | diff --git a/qapi/block-core.json b/qapi/block-core.json | |
dc9827a6 | 578 | index 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: |