1 file changed, 11 insertions(+), 4 deletions(-)
diff --git a/block/gluster.c b/block/gluster.c
-index 398976bc66..523304835e 100644
+index 592e71b22a..aebfece6eb 100644
--- a/block/gluster.c
+++ b/block/gluster.c
@@ -42,7 +42,7 @@
1 file changed, 2 insertions(+)
diff --git a/block/rbd.c b/block/rbd.c
-index 8f183eba2a..458f6bd7eb 100644
+index def96292e0..a4b8fb482c 100644
--- a/block/rbd.c
+++ b/block/rbd.c
@@ -820,6 +820,8 @@ static int qemu_rbd_connect(rados_t *cluster, rados_ioctx_t *io_ctx,
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/block/gluster.c b/block/gluster.c
-index 523304835e..80b75cb96c 100644
+index aebfece6eb..3b7ee2f649 100644
--- a/block/gluster.c
+++ b/block/gluster.c
@@ -57,6 +57,7 @@ typedef struct GlusterAIOCB {
- error_report_err(local_err);
- ret = -1;
- goto out;
-+ if (!blk1) {
-+ ret = -1;
-+ goto out;
-+ }
- }
+- }
- if (!drv->create_opts) {
- error_report("Format driver '%s' does not support image creation",
- drv->format_name);
- proto_drv->format_name);
- ret = -1;
- goto out;
-- }
++ if (!blk1) {
++ ret = -1;
++ goto out;
++ }
+ }
- create_opts = qemu_opts_append(create_opts, drv->create_opts);
- create_opts = qemu_opts_append(create_opts, proto_drv->create_opts);
--
-- opts = qemu_opts_create(create_opts, NULL, 0, &error_abort);
+- opts = qemu_opts_create(create_opts, NULL, 0, &error_abort);
+-
- size = blk_getlength(blk1);
- if (size < 0) {
- error_report("Failed to get size for '%s'", in.filename);
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
---
block/monitor/block-hmp-cmds.c | 4 ++-
- pve-backup.c | 59 ++++++++++++++++++++++++++--------
+ pve-backup.c | 57 +++++++++++++++++++++++++++-------
qapi/block-core.json | 6 ++++
- 3 files changed, 55 insertions(+), 14 deletions(-)
+ 3 files changed, 54 insertions(+), 13 deletions(-)
diff --git a/block/monitor/block-hmp-cmds.c b/block/monitor/block-hmp-cmds.c
index 3c06734e6d..4481b60a5c 100644
qemu_co_mutex_lock(&backup_state.dump_callback_mutex);
// avoid deadlock if job is cancelled
-@@ -147,16 +152,28 @@ pvebackup_co_dump_pbs_cb(
+@@ -147,17 +152,29 @@ pvebackup_co_dump_pbs_cb(
return -1;
}
- pbs_res = proxmox_backup_co_write_data(backup_state.pbs, di->dev_id, buf, start, size, &local_err);
+- qemu_co_mutex_unlock(&backup_state.dump_callback_mutex);
+ uint64_t transferred = 0;
+ uint64_t reused = 0;
+ while (transferred < size) {
+ uint64_t left = size - transferred;
+ uint64_t to_transfer = left < di->block_size ? left : di->block_size;
-+
+
+- if (pbs_res < 0) {
+- pvebackup_propagate_error(local_err);
+- return pbs_res;
+- } else {
+- size_t reused = (pbs_res == 0) ? size : 0;
+- pvebackup_add_transfered_bytes(size, !buf ? size : 0, reused);
+ pbs_res = proxmox_backup_co_write_data(backup_state.pbs, di->dev_id,
+ is_zero_block ? NULL : buf + transferred, start + transferred,
+ to_transfer, &local_err);
+ }
+
+ reused += pbs_res == 0 ? to_transfer : 0;
-+ }
-+
- qemu_co_mutex_unlock(&backup_state.dump_callback_mutex);
--
-- if (pbs_res < 0) {
-- pvebackup_propagate_error(local_err);
-- return pbs_res;
-- } else {
-- size_t reused = (pbs_res == 0) ? size : 0;
-- pvebackup_add_transfered_bytes(size, !buf ? size : 0, reused);
-- }
-+ pvebackup_add_transfered_bytes(size, is_zero_block ? size : 0, reused);
+ }
++ qemu_co_mutex_unlock(&backup_state.dump_callback_mutex);
++ pvebackup_add_transfered_bytes(size, is_zero_block ? size : 0, reused);
++
return size;
}
+
@@ -178,6 +195,7 @@ pvebackup_co_dump_vma_cb(
int ret = -1;
[add new force parameter to job_cancel_sync calls]
Signed-off-by: Fabian Ebner <f.ebner@proxmox.com>
---
- pve-backup.c | 169 +++++++++++++++------------------------------------
- 1 file changed, 50 insertions(+), 119 deletions(-)
+ pve-backup.c | 167 +++++++++++++++------------------------------------
+ 1 file changed, 49 insertions(+), 118 deletions(-)
diff --git a/pve-backup.c b/pve-backup.c
index f90abaa50a..63c686463f 100644
proxmox_backup_abort(backup_state.pbs, "backup canceled");
}
-+ /* it's enough to cancel one job in the transaction, the rest will follow
-+ * automatically */
-+ GList *bdi = g_list_first(backup_state.di_list);
-+ BlockJob *cancel_job = bdi && bdi->data ?
-+ ((PVEBackupDevInfo *)bdi->data)->job :
-+ NULL;
-+
-+ /* ref the job before releasing the mutex, just to be safe */
-+ if (cancel_job) {
-+ job_ref(&cancel_job->job);
-+ }
-+
-+ /* job_cancel_sync may enter the job, so we need to release the
-+ * backup_mutex to avoid deadlock */
- qemu_mutex_unlock(&backup_state.backup_mutex);
-
+- qemu_mutex_unlock(&backup_state.backup_mutex);
+-
- for(;;) {
-
- BlockJob *next_job = NULL;
- while (l) {
- PVEBackupDevInfo *di = (PVEBackupDevInfo *)l->data;
- l = g_list_next(l);
--
++ /* it's enough to cancel one job in the transaction, the rest will follow
++ * automatically */
++ GList *bdi = g_list_first(backup_state.di_list);
++ BlockJob *cancel_job = bdi && bdi->data ?
++ ((PVEBackupDevInfo *)bdi->data)->job :
++ NULL;
+
- BlockJob *job = lookup_active_block_job(di);
- if (job != NULL) {
- next_job = job;
- break;
- }
- }
--
++ /* ref the job before releasing the mutex, just to be safe */
++ if (cancel_job) {
++ job_ref(&cancel_job->job);
++ }
+
- qemu_mutex_unlock(&backup_state.backup_mutex);
--
++ /* job_cancel_sync may enter the job, so we need to release the
++ * backup_mutex to avoid deadlock */
++ qemu_mutex_unlock(&backup_state.backup_mutex);
+
- if (next_job) {
- AioContext *aio_context = next_job->job.aio_context;
- aio_context_acquire(aio_context);
- assert(!qemu_in_coroutine());
+ PVEBackupDevInfo *di = opaque;
+ di->completed_ret = ret;
-
++
+ /*
+ * Schedule stream cleanup in async coroutine. close_image and finish might
+ * take a while, so we can't block on them here. This way it also doesn't
+ aio_context_release(job_ctx);
+ aio_co_enter(data->ctx, data->co);
+}
-+
+
+static void coroutine_fn pvebackup_co_cancel(void *opaque)
+{
Error *cancel_err = NULL;
- if (!job || local_err != NULL) {
- Error *create_job_err = NULL;
- error_setg(&create_job_err, "backup_job_create failed: %s",
+- local_err ? error_get_pretty(local_err) : "null");
+ di->job = job;
-+
+
+- pvebackup_propagate_error(create_job_err);
+ if (!job || local_err) {
+ error_setg(errp, "backup_job_create failed: %s",
- local_err ? error_get_pretty(local_err) : "null");
--
-- pvebackup_propagate_error(create_job_err);
++ local_err ? error_get_pretty(local_err) : "null");
break;
}
Acked-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
---
- vma-reader.c | 60 ++++++++++---------
- vma.c | 159 +++++++++++++++++++++++++++++----------------------
+ vma-reader.c | 64 ++++++++++++---------
+ vma.c | 157 +++++++++++++++++++++++++++++----------------------
vma.h | 2 +-
- 3 files changed, 125 insertions(+), 96 deletions(-)
+ 3 files changed, 126 insertions(+), 97 deletions(-)
diff --git a/vma-reader.c b/vma-reader.c
index 4f4ee2b47b..844d95a5ba 100644
+ assert(target != NULL || skip);
assert(dev_id);
- assert(vmar->rstate[dev_id].target == NULL);
-+ assert(vmar->rstate[dev_id].target == NULL && !vmar->rstate[dev_id].skip);
-
+-
- int64_t size = blk_getlength(target);
- int64_t size_diff = size - vmar->devinfo[dev_id].size;
-+ if (target != NULL) {
-+ int64_t size = blk_getlength(target);
-+ int64_t size_diff = size - vmar->devinfo[dev_id].size;
-
+-
- /* storage types can have different size restrictions, so it
- * is not always possible to create an image with exact size.
- * So we tolerate a size difference up to 4MB.
- "unexpected size %zd != %zd", vmar->devinfo[dev_id].devname,
- size, vmar->devinfo[dev_id].size);
- return -1;
++ assert(vmar->rstate[dev_id].target == NULL && !vmar->rstate[dev_id].skip);
++
++ if (target != NULL) {
++ int64_t size = blk_getlength(target);
++ int64_t size_diff = size - vmar->devinfo[dev_id].size;
++
+ /* storage types can have different size restrictions, so it
+ * is not always possible to create an image with exact size.
+ * So we tolerate a size difference up to 4MB.
+ } else {
+ devname = line + 5;
+ skip = true;
++ }
++ } else {
++ while (1) {
++ if (!try_parse_option(&line, "format", &format, inbuf) &&
++ !try_parse_option(&line, "throttling.bps", &bps, inbuf) &&
++ !try_parse_option(&line, "throttling.group", &group, inbuf) &&
++ !try_parse_option(&line, "cache", &cache, inbuf))
++ {
++ break;
++ }
}
- }
--
+
- uint64_t bps_value = 0;
- if (bps) {
- bps_value = verify_u64(bps);
- g_free(bps);
- }
--
++ if (bps) {
++ bps_value = verify_u64(bps);
++ g_free(bps);
++ }
+
- const char *path;
- bool write_zero;
- if (line[0] == '0' && line[1] == ':') {
- } else if (line[0] == '1' && line[1] == ':') {
- path = line + 2;
- write_zero = true;
- } else {
+- } else {
- g_error("read map failed - parse error ('%s')", inbuf);
-+ while (1) {
-+ if (!try_parse_option(&line, "format", &format, inbuf) &&
-+ !try_parse_option(&line, "throttling.bps", &bps, inbuf) &&
-+ !try_parse_option(&line, "throttling.group", &group, inbuf) &&
-+ !try_parse_option(&line, "cache", &cache, inbuf))
-+ {
-+ break;
-+ }
-+ }
-+
-+ if (bps) {
-+ bps_value = verify_u64(bps);
-+ g_free(bps);
-+ }
-+
+ if (line[0] == '0' && line[1] == ':') {
+ path = line + 2;
+ write_zero = false;
backup_time,
dump_cb_block_size,
diff --git a/qapi/block-core.json b/qapi/block-core.json
-index c5023710f5..619e13b9b1 100644
+index d089328a1f..705f0c97ba 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -821,6 +821,8 @@
##
# @BlockdevOptionsNVMe:
---
-2.30.2
-
Signed-off-by: Fabian Ebner <f.ebner@proxmox.com>
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
---
- pve-backup.c | 13 +++++++++++++
- 1 file changed, 13 insertions(+)
+ pve-backup.c | 25 ++++++++++++++++++++-----
+ 1 file changed, 20 insertions(+), 5 deletions(-)
-Index: pve-qemu-kvm-6.2.0/pve-backup.c
-===================================================================
---- pve-qemu-kvm-6.2.0.orig/pve-backup.c
-+++ pve-qemu-kvm-6.2.0/pve-backup.c
-@@ -316,6 +316,14 @@ static void coroutine_fn pvebackup_co_co
+diff --git a/pve-backup.c b/pve-backup.c
+index 5bed6f4014..0c34428713 100644
+--- a/pve-backup.c
++++ b/pve-backup.c
+@@ -316,6 +316,14 @@ static void coroutine_fn pvebackup_co_complete_stream(void *opaque)
}
}
// remove self from job list
backup_state.di_list = g_list_remove(backup_state.di_list, di);
-@@ -491,9 +499,12 @@ static void create_backup_jobs_bh(void *
+@@ -491,9 +499,12 @@ static void create_backup_jobs_bh(void *opaque) {
bitmap_mode, false, NULL, &perf, BLOCKDEV_ON_ERROR_REPORT, BLOCKDEV_ON_ERROR_REPORT,
JOB_DEFAULT, pvebackup_complete_cb, di, backup_state.txn, &local_err);
if (!job || local_err) {
error_setg(errp, "backup_job_create failed: %s",
-@@ -521,12 +532,16 @@ static void create_backup_jobs_bh(void *
+@@ -521,12 +532,16 @@ static void create_backup_jobs_bh(void *opaque) {
di->target = NULL;
}
1 file changed, 39 insertions(+), 22 deletions(-)
diff --git a/pve-backup.c b/pve-backup.c
-index cd45e66a61..be21027dad 100644
+index 0c34428713..2e22030eec 100644
--- a/pve-backup.c
+++ b/pve-backup.c
-@@ -352,15 +352,42 @@ static void pvebackup_complete_cb(void *opaque, int ret)
+@@ -355,15 +355,42 @@ static void pvebackup_complete_cb(void *opaque, int ret)
/*
* job_cancel(_sync) does not like to be called from coroutines, so defer to
aio_co_enter(data->ctx, data->co);
}
-@@ -381,22 +408,12 @@ void coroutine_fn qmp_backup_cancel(Error **errp)
+@@ -384,22 +411,12 @@ void coroutine_fn qmp_backup_cancel(Error **errp)
proxmox_backup_abort(backup_state.pbs, "backup canceled");
}