Compare commits
11 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
14afbdd55f | ||
![]() |
54d1666680 | ||
![]() |
49125e1708 | ||
![]() |
b242e7f196 | ||
![]() |
c2abb73df7 | ||
![]() |
5bdf1bebba | ||
![]() |
99c80e7492 | ||
![]() |
9664f5a132 | ||
![]() |
b37841aa1a | ||
![]() |
822c99f3c3 | ||
![]() |
51df4937bf |
30
debian/changelog
vendored
30
debian/changelog
vendored
@@ -1,3 +1,33 @@
|
||||
pve-qemu-kvm (9.0.0-6) bookworm; urgency=medium
|
||||
|
||||
* fix a regression in the zeroinit block driver that prevented importing and
|
||||
cloning disks to RBD storages which are not using the krbd setting
|
||||
|
||||
-- Proxmox Support Team <support@proxmox.com> Mon, 08 Jul 2024 16:11:15 +0200
|
||||
|
||||
pve-qemu-kvm (9.0.0-5) bookworm; urgency=medium
|
||||
|
||||
* backport fix for CVE-2024-4467 to prevent malicious qcow2 image files from
|
||||
already causing bad effects if being queried via 'qemu-img info'. For
|
||||
Proxmox VE, this is an additional safe guard, as currently it directly
|
||||
creates and manages the qcow2 images used by VMs and does not allow
|
||||
unprivileged users to import them
|
||||
|
||||
* fix #4726: code cleanup: avoid superfluous check in vma backup code
|
||||
|
||||
-- Proxmox Support Team <support@proxmox.com> Wed, 03 Jul 2024 13:13:35 +0200
|
||||
|
||||
pve-qemu-kvm (9.0.0-4) bookworm; urgency=medium
|
||||
|
||||
* fix crash after saving a snapshot without including VM state when a VirtIO
|
||||
block device with iothread is configured.
|
||||
|
||||
* fix edge case in error handling when opening a block device from PBS fails
|
||||
|
||||
* minor code cleanup in backup code
|
||||
|
||||
-- Proxmox Support Team <support@proxmox.com> Mon, 01 Jul 2024 11:26:11 +0200
|
||||
|
||||
pve-qemu-kvm (9.0.0-3) bookworm; urgency=medium
|
||||
|
||||
* fix crash when doing resize after hotplugging a disk using io_uring
|
||||
|
107
debian/patches/extra/0019-qcow2-Don-t-open-data_file-with-BDRV_O_NO_IO.patch
vendored
Normal file
107
debian/patches/extra/0019-qcow2-Don-t-open-data_file-with-BDRV_O_NO_IO.patch
vendored
Normal file
@@ -0,0 +1,107 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Kevin Wolf <kwolf@redhat.com>
|
||||
Date: Tue, 2 Jul 2024 18:39:40 +0200
|
||||
Subject: [PATCH] qcow2: Don't open data_file with BDRV_O_NO_IO
|
||||
|
||||
One use case for 'qemu-img info' is verifying that untrusted images
|
||||
don't reference an unwanted external file, be it as a backing file or an
|
||||
external data file. To make sure that calling 'qemu-img info' can't
|
||||
already have undesired side effects with a malicious image, just don't
|
||||
open the data file at all with BDRV_O_NO_IO. If nothing ever tries to do
|
||||
I/O, we don't need to have it open.
|
||||
|
||||
This changes the output of iotests case 061, which used 'qemu-img info'
|
||||
to show that opening an image with an invalid data file fails. After
|
||||
this patch, it succeeds. Replace this part of the test with a qemu-io
|
||||
call, but keep the final 'qemu-img info' to show that the invalid data
|
||||
file is correctly displayed in the output.
|
||||
|
||||
Fixes: CVE-2024-4467
|
||||
Cc: qemu-stable@nongnu.org
|
||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||
Reviewed-by: Eric Blake <eblake@redhat.com>
|
||||
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
|
||||
Reviewed-by: Hanna Czenczek <hreitz@redhat.com>
|
||||
(picked from https://lore.kernel.org/qemu-devel/20240702163943.276618-2-kwolf@redhat.com/)
|
||||
Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
|
||||
---
|
||||
block/qcow2.c | 17 ++++++++++++++++-
|
||||
tests/qemu-iotests/061 | 6 ++++--
|
||||
tests/qemu-iotests/061.out | 8 ++++++--
|
||||
3 files changed, 26 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/block/qcow2.c b/block/qcow2.c
|
||||
index 956128b409..4c78665bcb 100644
|
||||
--- a/block/qcow2.c
|
||||
+++ b/block/qcow2.c
|
||||
@@ -1636,7 +1636,22 @@ qcow2_do_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
- if (open_data_file) {
|
||||
+ if (open_data_file && (flags & BDRV_O_NO_IO)) {
|
||||
+ /*
|
||||
+ * Don't open the data file for 'qemu-img info' so that it can be used
|
||||
+ * to verify that an untrusted qcow2 image doesn't refer to external
|
||||
+ * files.
|
||||
+ *
|
||||
+ * Note: This still makes has_data_file() return true.
|
||||
+ */
|
||||
+ if (s->incompatible_features & QCOW2_INCOMPAT_DATA_FILE) {
|
||||
+ s->data_file = NULL;
|
||||
+ } else {
|
||||
+ s->data_file = bs->file;
|
||||
+ }
|
||||
+ qdict_extract_subqdict(options, NULL, "data-file.");
|
||||
+ qdict_del(options, "data-file");
|
||||
+ } else if (open_data_file) {
|
||||
/* Open external data file */
|
||||
bdrv_graph_co_rdunlock();
|
||||
s->data_file = bdrv_co_open_child(NULL, options, "data-file", bs,
|
||||
diff --git a/tests/qemu-iotests/061 b/tests/qemu-iotests/061
|
||||
index 53c7d428e3..b71ac097d1 100755
|
||||
--- a/tests/qemu-iotests/061
|
||||
+++ b/tests/qemu-iotests/061
|
||||
@@ -326,12 +326,14 @@ $QEMU_IMG amend -o "data_file=foo" "$TEST_IMG"
|
||||
echo
|
||||
_make_test_img -o "compat=1.1,data_file=$TEST_IMG.data" 64M
|
||||
$QEMU_IMG amend -o "data_file=foo" "$TEST_IMG"
|
||||
-_img_info --format-specific
|
||||
+$QEMU_IO -c "read 0 4k" "$TEST_IMG" 2>&1 | _filter_testdir | _filter_imgfmt
|
||||
+$QEMU_IO -c "open -o data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG" -c "read 0 4k" | _filter_qemu_io
|
||||
TEST_IMG="data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG" _img_info --format-specific --image-opts
|
||||
|
||||
echo
|
||||
$QEMU_IMG amend -o "data_file=" --image-opts "data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG"
|
||||
-_img_info --format-specific
|
||||
+$QEMU_IO -c "read 0 4k" "$TEST_IMG" 2>&1 | _filter_testdir | _filter_imgfmt
|
||||
+$QEMU_IO -c "open -o data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG" -c "read 0 4k" | _filter_qemu_io
|
||||
TEST_IMG="data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG" _img_info --format-specific --image-opts
|
||||
|
||||
echo
|
||||
diff --git a/tests/qemu-iotests/061.out b/tests/qemu-iotests/061.out
|
||||
index 139fc68177..24c33add7c 100644
|
||||
--- a/tests/qemu-iotests/061.out
|
||||
+++ b/tests/qemu-iotests/061.out
|
||||
@@ -545,7 +545,9 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
|
||||
qemu-img: data-file can only be set for images that use an external data file
|
||||
|
||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 data_file=TEST_DIR/t.IMGFMT.data
|
||||
-qemu-img: Could not open 'TEST_DIR/t.IMGFMT': Could not open 'foo': No such file or directory
|
||||
+qemu-io: can't open device TEST_DIR/t.IMGFMT: Could not open 'foo': No such file or directory
|
||||
+read 4096/4096 bytes at offset 0
|
||||
+4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
image: TEST_DIR/t.IMGFMT
|
||||
file format: IMGFMT
|
||||
virtual size: 64 MiB (67108864 bytes)
|
||||
@@ -560,7 +562,9 @@ Format specific information:
|
||||
corrupt: false
|
||||
extended l2: false
|
||||
|
||||
-qemu-img: Could not open 'TEST_DIR/t.IMGFMT': 'data-file' is required for this image
|
||||
+qemu-io: can't open device TEST_DIR/t.IMGFMT: 'data-file' is required for this image
|
||||
+read 4096/4096 bytes at offset 0
|
||||
+4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
image: TEST_DIR/t.IMGFMT
|
||||
file format: IMGFMT
|
||||
virtual size: 64 MiB (67108864 bytes)
|
241
debian/patches/extra/0020-block-Parse-filenames-only-when-explicitly-requested.patch
vendored
Normal file
241
debian/patches/extra/0020-block-Parse-filenames-only-when-explicitly-requested.patch
vendored
Normal file
@@ -0,0 +1,241 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Kevin Wolf <kwolf@redhat.com>
|
||||
Date: Tue, 2 Jul 2024 18:39:43 +0200
|
||||
Subject: [PATCH] block: Parse filenames only when explicitly requested
|
||||
|
||||
When handling image filenames from legacy options such as -drive or from
|
||||
tools, these filenames are parsed for protocol prefixes, including for
|
||||
the json:{} pseudo-protocol.
|
||||
|
||||
This behaviour is intended for filenames that come directly from the
|
||||
command line and for backing files, which may come from the image file
|
||||
itself. Higher level management tools generally take care to verify that
|
||||
untrusted images don't contain a bad (or any) backing file reference;
|
||||
'qemu-img info' is a suitable tool for this.
|
||||
|
||||
However, for other files that can be referenced in images, such as
|
||||
qcow2 data files or VMDK extents, the string from the image file is
|
||||
usually not verified by management tools - and 'qemu-img info' wouldn't
|
||||
be suitable because in contrast to backing files, it already opens these
|
||||
other referenced files. So here the string should be interpreted as a
|
||||
literal local filename. More complex configurations need to be specified
|
||||
explicitly on the command line or in QMP.
|
||||
|
||||
This patch changes bdrv_open_inherit() so that it only parses filenames
|
||||
if a new parameter parse_filename is true. It is set for the top level
|
||||
in bdrv_open(), for the file child and for the backing file child. All
|
||||
other callers pass false and disable filename parsing this way.
|
||||
|
||||
Cc: qemu-stable@nongnu.org
|
||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||
Reviewed-by: Eric Blake <eblake@redhat.com>
|
||||
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
|
||||
Reviewed-by: Hanna Czenczek <hreitz@redhat.com>
|
||||
(picked from https://lore.kernel.org/qemu-devel/20240702163943.276618-5-kwolf@redhat.com/)
|
||||
Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
|
||||
---
|
||||
block.c | 90 ++++++++++++++++++++++++++++++++++++---------------------
|
||||
1 file changed, 57 insertions(+), 33 deletions(-)
|
||||
|
||||
diff --git a/block.c b/block.c
|
||||
index 468cf5e67d..50bdd197b7 100644
|
||||
--- a/block.c
|
||||
+++ b/block.c
|
||||
@@ -86,6 +86,7 @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
|
||||
BlockDriverState *parent,
|
||||
const BdrvChildClass *child_class,
|
||||
BdrvChildRole child_role,
|
||||
+ bool parse_filename,
|
||||
Error **errp);
|
||||
|
||||
static bool bdrv_recurse_has_child(BlockDriverState *bs,
|
||||
@@ -2058,7 +2059,8 @@ static void parse_json_protocol(QDict *options, const char **pfilename,
|
||||
* block driver has been specified explicitly.
|
||||
*/
|
||||
static int bdrv_fill_options(QDict **options, const char *filename,
|
||||
- int *flags, Error **errp)
|
||||
+ int *flags, bool allow_parse_filename,
|
||||
+ Error **errp)
|
||||
{
|
||||
const char *drvname;
|
||||
bool protocol = *flags & BDRV_O_PROTOCOL;
|
||||
@@ -2100,7 +2102,7 @@ static int bdrv_fill_options(QDict **options, const char *filename,
|
||||
if (protocol && filename) {
|
||||
if (!qdict_haskey(*options, "filename")) {
|
||||
qdict_put_str(*options, "filename", filename);
|
||||
- parse_filename = true;
|
||||
+ parse_filename = allow_parse_filename;
|
||||
} else {
|
||||
error_setg(errp, "Can't specify 'file' and 'filename' options at "
|
||||
"the same time");
|
||||
@@ -3663,7 +3665,8 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
|
||||
}
|
||||
|
||||
backing_hd = bdrv_open_inherit(backing_filename, reference, options, 0, bs,
|
||||
- &child_of_bds, bdrv_backing_role(bs), errp);
|
||||
+ &child_of_bds, bdrv_backing_role(bs), true,
|
||||
+ errp);
|
||||
if (!backing_hd) {
|
||||
bs->open_flags |= BDRV_O_NO_BACKING;
|
||||
error_prepend(errp, "Could not open backing file: ");
|
||||
@@ -3697,7 +3700,8 @@ free_exit:
|
||||
static BlockDriverState *
|
||||
bdrv_open_child_bs(const char *filename, QDict *options, const char *bdref_key,
|
||||
BlockDriverState *parent, const BdrvChildClass *child_class,
|
||||
- BdrvChildRole child_role, bool allow_none, Error **errp)
|
||||
+ BdrvChildRole child_role, bool allow_none,
|
||||
+ bool parse_filename, Error **errp)
|
||||
{
|
||||
BlockDriverState *bs = NULL;
|
||||
QDict *image_options;
|
||||
@@ -3728,7 +3732,8 @@ bdrv_open_child_bs(const char *filename, QDict *options, const char *bdref_key,
|
||||
}
|
||||
|
||||
bs = bdrv_open_inherit(filename, reference, image_options, 0,
|
||||
- parent, child_class, child_role, errp);
|
||||
+ parent, child_class, child_role, parse_filename,
|
||||
+ errp);
|
||||
if (!bs) {
|
||||
goto done;
|
||||
}
|
||||
@@ -3738,6 +3743,33 @@ done:
|
||||
return bs;
|
||||
}
|
||||
|
||||
+static BdrvChild *bdrv_open_child_common(const char *filename,
|
||||
+ QDict *options, const char *bdref_key,
|
||||
+ BlockDriverState *parent,
|
||||
+ const BdrvChildClass *child_class,
|
||||
+ BdrvChildRole child_role,
|
||||
+ bool allow_none, bool parse_filename,
|
||||
+ Error **errp)
|
||||
+{
|
||||
+ BlockDriverState *bs;
|
||||
+ BdrvChild *child;
|
||||
+
|
||||
+ GLOBAL_STATE_CODE();
|
||||
+
|
||||
+ bs = bdrv_open_child_bs(filename, options, bdref_key, parent, child_class,
|
||||
+ child_role, allow_none, parse_filename, errp);
|
||||
+ if (bs == NULL) {
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ bdrv_graph_wrlock();
|
||||
+ child = bdrv_attach_child(parent, bs, bdref_key, child_class, child_role,
|
||||
+ errp);
|
||||
+ bdrv_graph_wrunlock();
|
||||
+
|
||||
+ return child;
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* Opens a disk image whose options are given as BlockdevRef in another block
|
||||
* device's options.
|
||||
@@ -3761,27 +3793,15 @@ BdrvChild *bdrv_open_child(const char *filename,
|
||||
BdrvChildRole child_role,
|
||||
bool allow_none, Error **errp)
|
||||
{
|
||||
- BlockDriverState *bs;
|
||||
- BdrvChild *child;
|
||||
-
|
||||
- GLOBAL_STATE_CODE();
|
||||
-
|
||||
- bs = bdrv_open_child_bs(filename, options, bdref_key, parent, child_class,
|
||||
- child_role, allow_none, errp);
|
||||
- if (bs == NULL) {
|
||||
- return NULL;
|
||||
- }
|
||||
-
|
||||
- bdrv_graph_wrlock();
|
||||
- child = bdrv_attach_child(parent, bs, bdref_key, child_class, child_role,
|
||||
- errp);
|
||||
- bdrv_graph_wrunlock();
|
||||
-
|
||||
- return child;
|
||||
+ return bdrv_open_child_common(filename, options, bdref_key, parent,
|
||||
+ child_class, child_role, allow_none, false,
|
||||
+ errp);
|
||||
}
|
||||
|
||||
/*
|
||||
- * Wrapper on bdrv_open_child() for most popular case: open primary child of bs.
|
||||
+ * This does mostly the same as bdrv_open_child(), but for opening the primary
|
||||
+ * child of a node. A notable difference from bdrv_open_child() is that it
|
||||
+ * enables filename parsing for protocol names (including json:).
|
||||
*
|
||||
* @parent can move to a different AioContext in this function.
|
||||
*/
|
||||
@@ -3796,8 +3816,8 @@ int bdrv_open_file_child(const char *filename,
|
||||
role = parent->drv->is_filter ?
|
||||
(BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY) : BDRV_CHILD_IMAGE;
|
||||
|
||||
- if (!bdrv_open_child(filename, options, bdref_key, parent,
|
||||
- &child_of_bds, role, false, errp))
|
||||
+ if (!bdrv_open_child_common(filename, options, bdref_key, parent,
|
||||
+ &child_of_bds, role, false, true, errp))
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -3842,7 +3862,8 @@ BlockDriverState *bdrv_open_blockdev_ref(BlockdevRef *ref, Error **errp)
|
||||
|
||||
}
|
||||
|
||||
- bs = bdrv_open_inherit(NULL, reference, qdict, 0, NULL, NULL, 0, errp);
|
||||
+ bs = bdrv_open_inherit(NULL, reference, qdict, 0, NULL, NULL, 0, false,
|
||||
+ errp);
|
||||
obj = NULL;
|
||||
qobject_unref(obj);
|
||||
visit_free(v);
|
||||
@@ -3932,7 +3953,7 @@ static BlockDriverState * no_coroutine_fn
|
||||
bdrv_open_inherit(const char *filename, const char *reference, QDict *options,
|
||||
int flags, BlockDriverState *parent,
|
||||
const BdrvChildClass *child_class, BdrvChildRole child_role,
|
||||
- Error **errp)
|
||||
+ bool parse_filename, Error **errp)
|
||||
{
|
||||
int ret;
|
||||
BlockBackend *file = NULL;
|
||||
@@ -3980,9 +4001,11 @@ bdrv_open_inherit(const char *filename, const char *reference, QDict *options,
|
||||
}
|
||||
|
||||
/* json: syntax counts as explicit options, as if in the QDict */
|
||||
- parse_json_protocol(options, &filename, &local_err);
|
||||
- if (local_err) {
|
||||
- goto fail;
|
||||
+ if (parse_filename) {
|
||||
+ parse_json_protocol(options, &filename, &local_err);
|
||||
+ if (local_err) {
|
||||
+ goto fail;
|
||||
+ }
|
||||
}
|
||||
|
||||
bs->explicit_options = qdict_clone_shallow(options);
|
||||
@@ -4007,7 +4030,8 @@ bdrv_open_inherit(const char *filename, const char *reference, QDict *options,
|
||||
parent->open_flags, parent->options);
|
||||
}
|
||||
|
||||
- ret = bdrv_fill_options(&options, filename, &flags, &local_err);
|
||||
+ ret = bdrv_fill_options(&options, filename, &flags, parse_filename,
|
||||
+ &local_err);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
@@ -4076,7 +4100,7 @@ bdrv_open_inherit(const char *filename, const char *reference, QDict *options,
|
||||
|
||||
file_bs = bdrv_open_child_bs(filename, options, "file", bs,
|
||||
&child_of_bds, BDRV_CHILD_IMAGE,
|
||||
- true, &local_err);
|
||||
+ true, true, &local_err);
|
||||
if (local_err) {
|
||||
goto fail;
|
||||
}
|
||||
@@ -4225,7 +4249,7 @@ BlockDriverState *bdrv_open(const char *filename, const char *reference,
|
||||
GLOBAL_STATE_CODE();
|
||||
|
||||
return bdrv_open_inherit(filename, reference, options, flags, NULL,
|
||||
- NULL, 0, errp);
|
||||
+ NULL, 0, true, errp);
|
||||
}
|
||||
|
||||
/* Return true if the NULL-terminated @list contains @str */
|
@@ -27,7 +27,8 @@ Signed-off-by: Stefan Reiter <s.reiter@proxmox.com>
|
||||
[FE: further improve aborting
|
||||
adapt to removal of QEMUFileOps
|
||||
improve condition for entering final stage
|
||||
adapt to QAPI and other changes for 8.2]
|
||||
adapt to QAPI and other changes for 8.2
|
||||
make sure to not call vm_start() from coroutine]
|
||||
Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
|
||||
---
|
||||
hmp-commands-info.hx | 13 +
|
||||
@@ -35,13 +36,13 @@ Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
|
||||
include/migration/snapshot.h | 2 +
|
||||
include/monitor/hmp.h | 3 +
|
||||
migration/meson.build | 1 +
|
||||
migration/savevm-async.c | 531 +++++++++++++++++++++++++++++++++++
|
||||
migration/savevm-async.c | 538 +++++++++++++++++++++++++++++++++++
|
||||
monitor/hmp-cmds.c | 38 +++
|
||||
qapi/migration.json | 34 +++
|
||||
qapi/misc.json | 18 ++
|
||||
qemu-options.hx | 12 +
|
||||
system/vl.c | 10 +
|
||||
11 files changed, 679 insertions(+)
|
||||
11 files changed, 686 insertions(+)
|
||||
create mode 100644 migration/savevm-async.c
|
||||
|
||||
diff --git a/hmp-commands-info.hx b/hmp-commands-info.hx
|
||||
@@ -139,10 +140,10 @@ index 95d1cf2250..800f12a60d 100644
|
||||
'threadinfo.c',
|
||||
diff --git a/migration/savevm-async.c b/migration/savevm-async.c
|
||||
new file mode 100644
|
||||
index 0000000000..779e4e2a78
|
||||
index 0000000000..72cf6588c2
|
||||
--- /dev/null
|
||||
+++ b/migration/savevm-async.c
|
||||
@@ -0,0 +1,531 @@
|
||||
@@ -0,0 +1,538 @@
|
||||
+#include "qemu/osdep.h"
|
||||
+#include "migration/channel-savevm-async.h"
|
||||
+#include "migration/migration.h"
|
||||
@@ -570,29 +571,10 @@ index 0000000000..779e4e2a78
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+void coroutine_fn qmp_savevm_end(Error **errp)
|
||||
+static void coroutine_fn wait_for_close_co(void *opaque)
|
||||
+{
|
||||
+ int64_t timeout;
|
||||
+
|
||||
+ if (snap_state.state == SAVE_STATE_DONE) {
|
||||
+ error_set(errp, ERROR_CLASS_GENERIC_ERROR,
|
||||
+ "VM snapshot not started\n");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (snap_state.state == SAVE_STATE_ACTIVE) {
|
||||
+ snap_state.state = SAVE_STATE_CANCELLED;
|
||||
+ goto wait_for_close;
|
||||
+ }
|
||||
+
|
||||
+ if (snap_state.saved_vm_running) {
|
||||
+ vm_start();
|
||||
+ snap_state.saved_vm_running = false;
|
||||
+ }
|
||||
+
|
||||
+ snap_state.state = SAVE_STATE_DONE;
|
||||
+
|
||||
+wait_for_close:
|
||||
+ if (!snap_state.target) {
|
||||
+ DPRINTF("savevm-end: no target file open\n");
|
||||
+ return;
|
||||
@@ -620,6 +602,32 @@ index 0000000000..779e4e2a78
|
||||
+ DPRINTF("savevm-end: cleanup done\n");
|
||||
+}
|
||||
+
|
||||
+void qmp_savevm_end(Error **errp)
|
||||
+{
|
||||
+ if (snap_state.state == SAVE_STATE_DONE) {
|
||||
+ error_set(errp, ERROR_CLASS_GENERIC_ERROR,
|
||||
+ "VM snapshot not started\n");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ Coroutine *wait_for_close = qemu_coroutine_create(wait_for_close_co, NULL);
|
||||
+
|
||||
+ if (snap_state.state == SAVE_STATE_ACTIVE) {
|
||||
+ snap_state.state = SAVE_STATE_CANCELLED;
|
||||
+ qemu_coroutine_enter(wait_for_close);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (snap_state.saved_vm_running) {
|
||||
+ vm_start();
|
||||
+ snap_state.saved_vm_running = false;
|
||||
+ }
|
||||
+
|
||||
+ snap_state.state = SAVE_STATE_DONE;
|
||||
+
|
||||
+ qemu_coroutine_enter(wait_for_close);
|
||||
+}
|
||||
+
|
||||
+int load_snapshot_from_blockdev(const char *filename, Error **errp)
|
||||
+{
|
||||
+ BlockBackend *be;
|
||||
@@ -773,7 +781,7 @@ index 8c65b90328..ed20d066cd 100644
|
||||
# @query-migrate:
|
||||
#
|
||||
diff --git a/qapi/misc.json b/qapi/misc.json
|
||||
index ec30e5c570..7147199a12 100644
|
||||
index ec30e5c570..3c68633f68 100644
|
||||
--- a/qapi/misc.json
|
||||
+++ b/qapi/misc.json
|
||||
@@ -454,6 +454,24 @@
|
||||
@@ -796,7 +804,7 @@ index ec30e5c570..7147199a12 100644
|
||||
+# Resume VM after a snapshot.
|
||||
+#
|
||||
+##
|
||||
+{ 'command': 'savevm-end', 'coroutine': true }
|
||||
+{ 'command': 'savevm-end' }
|
||||
+
|
||||
##
|
||||
# @CommandLineParameterType:
|
||||
|
@@ -193,7 +193,7 @@ index 32fd4a34fd..36a0cd8cc8 100644
|
||||
|
||||
/*
|
||||
diff --git a/migration/savevm-async.c b/migration/savevm-async.c
|
||||
index 779e4e2a78..bf36fc06d2 100644
|
||||
index 72cf6588c2..fb4e8ea689 100644
|
||||
--- a/migration/savevm-async.c
|
||||
+++ b/migration/savevm-async.c
|
||||
@@ -379,7 +379,7 @@ void qmp_savevm_start(const char *statefile, Error **errp)
|
||||
@@ -205,7 +205,7 @@ index 779e4e2a78..bf36fc06d2 100644
|
||||
|
||||
if (!snap_state.file) {
|
||||
error_set(errp, ERROR_CLASS_GENERIC_ERROR, "failed to open '%s'", statefile);
|
||||
@@ -496,7 +496,8 @@ int load_snapshot_from_blockdev(const char *filename, Error **errp)
|
||||
@@ -503,7 +503,8 @@ int load_snapshot_from_blockdev(const char *filename, Error **errp)
|
||||
blk_op_block_all(be, blocker);
|
||||
|
||||
/* restore the VM state */
|
||||
|
@@ -5,12 +5,13 @@ Subject: [PATCH] PVE: block: add the zeroinit block driver filter
|
||||
|
||||
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
|
||||
[FE: adapt to changed function signatures
|
||||
adhere to block graph lock requirements]
|
||||
adhere to block graph lock requirements
|
||||
use dedicated function to open file child]
|
||||
Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
|
||||
---
|
||||
block/meson.build | 1 +
|
||||
block/zeroinit.c | 214 ++++++++++++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 215 insertions(+)
|
||||
block/zeroinit.c | 207 ++++++++++++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 208 insertions(+)
|
||||
create mode 100644 block/zeroinit.c
|
||||
|
||||
diff --git a/block/meson.build b/block/meson.build
|
||||
@@ -27,10 +28,10 @@ index e1f03fd773..b530e117b5 100644
|
||||
system_ss.add(when: 'CONFIG_TCG', if_true: files('blkreplay.c'))
|
||||
diff --git a/block/zeroinit.c b/block/zeroinit.c
|
||||
new file mode 100644
|
||||
index 0000000000..696558d8d6
|
||||
index 0000000000..7998c9332d
|
||||
--- /dev/null
|
||||
+++ b/block/zeroinit.c
|
||||
@@ -0,0 +1,214 @@
|
||||
@@ -0,0 +1,207 @@
|
||||
+/*
|
||||
+ * Filter to fake a zero-initialized block device.
|
||||
+ *
|
||||
@@ -96,7 +97,6 @@ index 0000000000..696558d8d6
|
||||
+ Error **errp)
|
||||
+{
|
||||
+ BDRVZeroinitState *s = bs->opaque;
|
||||
+ BdrvChild *file = NULL;
|
||||
+ QemuOpts *opts;
|
||||
+ Error *local_err = NULL;
|
||||
+ int ret;
|
||||
@@ -112,15 +112,9 @@ index 0000000000..696558d8d6
|
||||
+ }
|
||||
+
|
||||
+ /* Open the raw file */
|
||||
+ file = bdrv_open_child(qemu_opt_get(opts, "x-next"), options, "next", bs,
|
||||
+ &child_of_bds,
|
||||
+ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY, false,
|
||||
+ &local_err);
|
||||
+ bdrv_graph_wrlock();
|
||||
+ bs->file = file;
|
||||
+ bdrv_graph_wrunlock();
|
||||
+ if (local_err) {
|
||||
+ ret = -EINVAL;
|
||||
+ ret = bdrv_open_file_child(qemu_opt_get(opts, "x-next"), options, "next",
|
||||
+ bs, &local_err);
|
||||
+ if (ret < 0) {
|
||||
+ error_propagate(errp, local_err);
|
||||
+ goto fail;
|
||||
+ }
|
||||
|
@@ -16,10 +16,10 @@ Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
|
||||
block/meson.build | 2 +
|
||||
meson.build | 5 +
|
||||
vma-reader.c | 870 ++++++++++++++++++++++++++++++++++++++++++++
|
||||
vma-writer.c | 818 +++++++++++++++++++++++++++++++++++++++++
|
||||
vma-writer.c | 817 +++++++++++++++++++++++++++++++++++++++++
|
||||
vma.c | 901 ++++++++++++++++++++++++++++++++++++++++++++++
|
||||
vma.h | 150 ++++++++
|
||||
6 files changed, 2746 insertions(+)
|
||||
6 files changed, 2745 insertions(+)
|
||||
create mode 100644 vma-reader.c
|
||||
create mode 100644 vma-writer.c
|
||||
create mode 100644 vma.c
|
||||
@@ -939,10 +939,10 @@ index 0000000000..d0b6721812
|
||||
+
|
||||
diff --git a/vma-writer.c b/vma-writer.c
|
||||
new file mode 100644
|
||||
index 0000000000..126b296647
|
||||
index 0000000000..a466652a5d
|
||||
--- /dev/null
|
||||
+++ b/vma-writer.c
|
||||
@@ -0,0 +1,818 @@
|
||||
@@ -0,0 +1,817 @@
|
||||
+/*
|
||||
+ * VMA: Virtual Machine Archive
|
||||
+ *
|
||||
@@ -1517,17 +1517,16 @@ index 0000000000..126b296647
|
||||
+ int i;
|
||||
+
|
||||
+ g_assert(vmaw != NULL);
|
||||
+ g_assert(status != NULL);
|
||||
+
|
||||
+ if (status) {
|
||||
+ status->status = vmaw->status;
|
||||
+ g_strlcpy(status->errmsg, vmaw->errmsg, sizeof(status->errmsg));
|
||||
+ for (i = 0; i <= 255; i++) {
|
||||
+ status->stream_info[i] = vmaw->stream_info[i];
|
||||
+ }
|
||||
+
|
||||
+ uuid_unparse_lower(vmaw->uuid, status->uuid_str);
|
||||
+ status->status = vmaw->status;
|
||||
+ g_strlcpy(status->errmsg, vmaw->errmsg, sizeof(status->errmsg));
|
||||
+ for (i = 0; i <= 255; i++) {
|
||||
+ status->stream_info[i] = vmaw->stream_info[i];
|
||||
+ }
|
||||
+
|
||||
+ uuid_unparse_lower(vmaw->uuid, status->uuid_str);
|
||||
+
|
||||
+ status->closed = vmaw->closed;
|
||||
+
|
||||
+ return vmaw->status;
|
||||
|
@@ -94,11 +94,11 @@ Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
|
||||
monitor/hmp-cmds.c | 72 +++
|
||||
proxmox-backup-client.c | 146 +++++
|
||||
proxmox-backup-client.h | 60 ++
|
||||
pve-backup.c | 1098 ++++++++++++++++++++++++++++++++
|
||||
pve-backup.c | 1092 ++++++++++++++++++++++++++++++++
|
||||
qapi/block-core.json | 233 +++++++
|
||||
qapi/common.json | 14 +
|
||||
qapi/machine.json | 16 +-
|
||||
14 files changed, 1717 insertions(+), 14 deletions(-)
|
||||
14 files changed, 1711 insertions(+), 14 deletions(-)
|
||||
create mode 100644 proxmox-backup-client.c
|
||||
create mode 100644 proxmox-backup-client.h
|
||||
create mode 100644 pve-backup.c
|
||||
@@ -586,10 +586,10 @@ index 0000000000..8cbf645b2c
|
||||
+#endif /* PROXMOX_BACKUP_CLIENT_H */
|
||||
diff --git a/pve-backup.c b/pve-backup.c
|
||||
new file mode 100644
|
||||
index 0000000000..9c13a92623
|
||||
index 0000000000..c755bf302b
|
||||
--- /dev/null
|
||||
+++ b/pve-backup.c
|
||||
@@ -0,0 +1,1098 @@
|
||||
@@ -0,0 +1,1092 @@
|
||||
+#include "proxmox-backup-client.h"
|
||||
+#include "vma.h"
|
||||
+
|
||||
@@ -626,7 +626,6 @@ index 0000000000..9c13a92623
|
||||
+ * ---end-bad-example--
|
||||
+ *
|
||||
+ * ==> Always use CoMutext inside coroutines.
|
||||
+ * ==> Never acquire/release AioContext withing coroutines (because that use QemuRecMutex)
|
||||
+ *
|
||||
+ */
|
||||
+
|
||||
@@ -679,7 +678,6 @@ index 0000000000..9c13a92623
|
||||
+ uint64_t block_size;
|
||||
+ uint8_t dev_id;
|
||||
+ int completed_ret; // INT_MAX if not completed
|
||||
+ char targetfile[PATH_MAX];
|
||||
+ BdrvDirtyBitmap *bitmap;
|
||||
+ BlockDriverState *target;
|
||||
+ BlockJob *job;
|
||||
@@ -1078,8 +1076,7 @@ index 0000000000..9c13a92623
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * backup_job_create can *not* be run from a coroutine (and requires an
|
||||
+ * acquired AioContext), so this can't either.
|
||||
+ * backup_job_create can *not* be run from a coroutine, so this can't either.
|
||||
+ * The caller is responsible that backup_mutex is held nonetheless.
|
||||
+ */
|
||||
+static void create_backup_jobs_bh(void *opaque) {
|
||||
@@ -1573,9 +1570,6 @@ index 0000000000..9c13a92623
|
||||
+ bdrv_co_unref(di->target);
|
||||
+ }
|
||||
+
|
||||
+ if (di->targetfile[0]) {
|
||||
+ unlink(di->targetfile);
|
||||
+ }
|
||||
+ g_free(di);
|
||||
+ }
|
||||
+ g_list_free(di_list);
|
||||
|
@@ -15,11 +15,11 @@ Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
|
||||
Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
|
||||
---
|
||||
block/meson.build | 2 +
|
||||
block/pbs.c | 307 +++++++++++++++++++++++++++++++++++++++++++
|
||||
block/pbs.c | 313 +++++++++++++++++++++++++++++++++++++++++++
|
||||
meson.build | 2 +-
|
||||
qapi/block-core.json | 29 ++++
|
||||
qapi/pragma.json | 1 +
|
||||
5 files changed, 340 insertions(+), 1 deletion(-)
|
||||
5 files changed, 346 insertions(+), 1 deletion(-)
|
||||
create mode 100644 block/pbs.c
|
||||
|
||||
diff --git a/block/meson.build b/block/meson.build
|
||||
@@ -37,10 +37,10 @@ index 6bba803f94..1945e04eeb 100644
|
||||
system_ss.add(files('block-ram-registrar.c'))
|
||||
diff --git a/block/pbs.c b/block/pbs.c
|
||||
new file mode 100644
|
||||
index 0000000000..dd72356bd3
|
||||
index 0000000000..aee66c2e93
|
||||
--- /dev/null
|
||||
+++ b/block/pbs.c
|
||||
@@ -0,0 +1,307 @@
|
||||
@@ -0,0 +1,313 @@
|
||||
+/*
|
||||
+ * Proxmox Backup Server read-only block driver
|
||||
+ */
|
||||
@@ -68,7 +68,7 @@ index 0000000000..dd72356bd3
|
||||
+
|
||||
+typedef struct {
|
||||
+ ProxmoxRestoreHandle *conn;
|
||||
+ char aid;
|
||||
+ uint8_t aid;
|
||||
+ int64_t length;
|
||||
+
|
||||
+ char *repository;
|
||||
@@ -201,12 +201,18 @@ index 0000000000..dd72356bd3
|
||||
+ }
|
||||
+
|
||||
+ /* acquire handle and length */
|
||||
+ s->aid = proxmox_restore_open_image(s->conn, s->archive, &pbs_error);
|
||||
+ if (s->aid < 0) {
|
||||
+ ret = proxmox_restore_open_image(s->conn, s->archive, &pbs_error);
|
||||
+ if (ret < 0) {
|
||||
+ if (pbs_error && errp) error_setg(errp, "PBS open_image failed: %s", pbs_error);
|
||||
+ if (pbs_error) proxmox_backup_free_error(pbs_error);
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+ if (ret > UINT8_MAX) {
|
||||
+ error_setg(errp, "PBS open_image returned an ID larger than %u", UINT8_MAX);
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+ s->aid = ret;
|
||||
+
|
||||
+ s->length = proxmox_restore_get_image_length(s->conn, s->aid, &pbs_error);
|
||||
+ if (s->length < 0) {
|
||||
+ if (pbs_error && errp) error_setg(errp, "PBS get_image_length failed: %s", pbs_error);
|
||||
|
@@ -174,10 +174,10 @@ index 0000000000..887e998b9e
|
||||
+ NULL);
|
||||
+}
|
||||
diff --git a/pve-backup.c b/pve-backup.c
|
||||
index 9c13a92623..9d480a8eec 100644
|
||||
index c755bf302b..5ebb6a3947 100644
|
||||
--- a/pve-backup.c
|
||||
+++ b/pve-backup.c
|
||||
@@ -1091,6 +1091,7 @@ ProxmoxSupportStatus *qmp_query_proxmox_support(Error **errp)
|
||||
@@ -1085,6 +1085,7 @@ ProxmoxSupportStatus *qmp_query_proxmox_support(Error **errp)
|
||||
ret->pbs_library_version = g_strdup(proxmox_backup_qemu_version());
|
||||
ret->pbs_dirty_bitmap = true;
|
||||
ret->pbs_dirty_bitmap_savevm = true;
|
||||
|
@@ -63,9 +63,9 @@ Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
|
||||
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
|
||||
---
|
||||
block/monitor/block-hmp-cmds.c | 1 +
|
||||
pve-backup.c | 143 ++++++++++++++++++++++++++++++++-
|
||||
pve-backup.c | 135 ++++++++++++++++++++++++++++++++-
|
||||
qapi/block-core.json | 10 ++-
|
||||
3 files changed, 150 insertions(+), 4 deletions(-)
|
||||
3 files changed, 142 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/block/monitor/block-hmp-cmds.c b/block/monitor/block-hmp-cmds.c
|
||||
index 5000c084c5..70b3de4c7e 100644
|
||||
@@ -80,7 +80,7 @@ index 5000c084c5..70b3de4c7e 100644
|
||||
|
||||
hmp_handle_error(mon, error);
|
||||
diff --git a/pve-backup.c b/pve-backup.c
|
||||
index 9d480a8eec..7cc1dd3724 100644
|
||||
index 5ebb6a3947..a747d12d3d 100644
|
||||
--- a/pve-backup.c
|
||||
+++ b/pve-backup.c
|
||||
@@ -7,9 +7,11 @@
|
||||
@@ -95,7 +95,7 @@ index 9d480a8eec..7cc1dd3724 100644
|
||||
#include "qapi/qmp/qerror.h"
|
||||
#include "qemu/cutils.h"
|
||||
|
||||
@@ -81,8 +83,15 @@ static void pvebackup_init(void)
|
||||
@@ -80,8 +82,15 @@ static void pvebackup_init(void)
|
||||
// initialize PVEBackupState at startup
|
||||
opts_init(pvebackup_init);
|
||||
|
||||
@@ -111,7 +111,7 @@ index 9d480a8eec..7cc1dd3724 100644
|
||||
size_t size;
|
||||
uint64_t block_size;
|
||||
uint8_t dev_id;
|
||||
@@ -355,6 +364,25 @@ static void pvebackup_complete_cb(void *opaque, int ret)
|
||||
@@ -353,6 +362,22 @@ static void pvebackup_complete_cb(void *opaque, int ret)
|
||||
PVEBackupDevInfo *di = opaque;
|
||||
di->completed_ret = ret;
|
||||
|
||||
@@ -121,9 +121,6 @@ index 9d480a8eec..7cc1dd3724 100644
|
||||
+ * - For snapshot_access, allows doing bdrv_unref() directly. Doing it via bdrv_co_unref() would
|
||||
+ * just spawn a BH calling bdrv_unref().
|
||||
+ * - For cbw, draining would need to spawn a BH.
|
||||
+ *
|
||||
+ * Note that the AioContext lock is already acquired by our caller, i.e.
|
||||
+ * job_finalize_single_locked()
|
||||
+ */
|
||||
+ if (di->fleecing.snapshot_access) {
|
||||
+ bdrv_unref(di->fleecing.snapshot_access);
|
||||
@@ -137,7 +134,7 @@ index 9d480a8eec..7cc1dd3724 100644
|
||||
/*
|
||||
* Needs to happen outside of coroutine, because it takes the graph write lock.
|
||||
*/
|
||||
@@ -522,9 +550,82 @@ static void create_backup_jobs_bh(void *opaque) {
|
||||
@@ -519,9 +544,77 @@ static void create_backup_jobs_bh(void *opaque) {
|
||||
}
|
||||
bdrv_drained_begin(di->bs);
|
||||
|
||||
@@ -182,11 +179,6 @@ index 9d480a8eec..7cc1dd3724 100644
|
||||
+ qdict_put_str(snapshot_access_opts, "driver", "snapshot-access");
|
||||
+ qdict_put_str(snapshot_access_opts, "file", bdrv_get_node_name(di->fleecing.cbw));
|
||||
+
|
||||
+ /*
|
||||
+ * Holding the AioContext lock here would cause a deadlock, because bdrv_open_driver()
|
||||
+ * will aquire it a second time. But it's allowed to be held exactly once when polling
|
||||
+ * and that happens when the bdrv_refresh_total_sectors() call is made there.
|
||||
+ */
|
||||
+ di->fleecing.snapshot_access =
|
||||
+ bdrv_open(NULL, NULL, snapshot_access_opts, BDRV_O_RDWR | BDRV_O_UNMAP, &local_err);
|
||||
+ if (!di->fleecing.snapshot_access) {
|
||||
@@ -222,7 +214,7 @@ index 9d480a8eec..7cc1dd3724 100644
|
||||
BLOCKDEV_ON_ERROR_REPORT, JOB_DEFAULT, pvebackup_complete_cb, di, backup_state.txn,
|
||||
&local_err);
|
||||
|
||||
@@ -580,6 +681,14 @@ static void create_backup_jobs_bh(void *opaque) {
|
||||
@@ -577,6 +670,14 @@ static void create_backup_jobs_bh(void *opaque) {
|
||||
aio_co_enter(data->ctx, data->co);
|
||||
}
|
||||
|
||||
@@ -237,7 +229,7 @@ index 9d480a8eec..7cc1dd3724 100644
|
||||
/*
|
||||
* Returns a list of device infos, which needs to be freed by the caller. In
|
||||
* case of an error, errp will be set, but the returned value might still be a
|
||||
@@ -587,6 +696,7 @@ static void create_backup_jobs_bh(void *opaque) {
|
||||
@@ -584,6 +685,7 @@ static void create_backup_jobs_bh(void *opaque) {
|
||||
*/
|
||||
static GList coroutine_fn GRAPH_RDLOCK *get_device_info(
|
||||
const char *devlist,
|
||||
@@ -245,7 +237,7 @@ index 9d480a8eec..7cc1dd3724 100644
|
||||
Error **errp)
|
||||
{
|
||||
gchar **devs = NULL;
|
||||
@@ -610,6 +720,31 @@ static GList coroutine_fn GRAPH_RDLOCK *get_device_info(
|
||||
@@ -607,6 +709,31 @@ static GList coroutine_fn GRAPH_RDLOCK *get_device_info(
|
||||
}
|
||||
PVEBackupDevInfo *di = g_new0(PVEBackupDevInfo, 1);
|
||||
di->bs = bs;
|
||||
@@ -277,7 +269,7 @@ index 9d480a8eec..7cc1dd3724 100644
|
||||
di_list = g_list_append(di_list, di);
|
||||
d++;
|
||||
}
|
||||
@@ -659,6 +794,7 @@ UuidInfo coroutine_fn *qmp_backup(
|
||||
@@ -656,6 +783,7 @@ UuidInfo coroutine_fn *qmp_backup(
|
||||
const char *devlist,
|
||||
bool has_speed, int64_t speed,
|
||||
bool has_max_workers, int64_t max_workers,
|
||||
@@ -285,7 +277,7 @@ index 9d480a8eec..7cc1dd3724 100644
|
||||
Error **errp)
|
||||
{
|
||||
assert(qemu_in_coroutine());
|
||||
@@ -687,7 +823,7 @@ UuidInfo coroutine_fn *qmp_backup(
|
||||
@@ -684,7 +812,7 @@ UuidInfo coroutine_fn *qmp_backup(
|
||||
format = has_format ? format : BACKUP_FORMAT_VMA;
|
||||
|
||||
bdrv_graph_co_rdlock();
|
||||
@@ -294,7 +286,7 @@ index 9d480a8eec..7cc1dd3724 100644
|
||||
bdrv_graph_co_rdunlock();
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
@@ -1095,5 +1231,6 @@ ProxmoxSupportStatus *qmp_query_proxmox_support(Error **errp)
|
||||
@@ -1089,5 +1217,6 @@ ProxmoxSupportStatus *qmp_query_proxmox_support(Error **errp)
|
||||
ret->query_bitmap_info = true;
|
||||
ret->pbs_masterkey = true;
|
||||
ret->backup_max_workers = true;
|
||||
|
@@ -96,10 +96,10 @@ index dc6cafe7fa..a27d2d7d9f 100644
|
||||
|
||||
#endif /* COPY_BEFORE_WRITE_H */
|
||||
diff --git a/pve-backup.c b/pve-backup.c
|
||||
index 7cc1dd3724..07709aa350 100644
|
||||
index a747d12d3d..4e730aa3da 100644
|
||||
--- a/pve-backup.c
|
||||
+++ b/pve-backup.c
|
||||
@@ -379,6 +379,15 @@ static void pvebackup_complete_cb(void *opaque, int ret)
|
||||
@@ -374,6 +374,15 @@ static void pvebackup_complete_cb(void *opaque, int ret)
|
||||
di->fleecing.snapshot_access = NULL;
|
||||
}
|
||||
if (di->fleecing.cbw) {
|
||||
|
2
debian/patches/series
vendored
2
debian/patches/series
vendored
@@ -16,6 +16,8 @@ extra/0015-target-i386-Give-IRQs-a-chance-when-resetting-HF_INH.patch
|
||||
extra/0016-target-i386-hyper-v-Correct-kvm_hv_handle_exit-retur.patch
|
||||
extra/0017-target-i386-disable-jmp_opt-if-EFLAGS.RF-is-1.patch
|
||||
extra/0018-target-i386-no-single-step-exception-after-MOV-or-PO.patch
|
||||
extra/0019-qcow2-Don-t-open-data_file-with-BDRV_O_NO_IO.patch
|
||||
extra/0020-block-Parse-filenames-only-when-explicitly-requested.patch
|
||||
bitmap-mirror/0001-drive-mirror-add-support-for-sync-bitmap-mode-never.patch
|
||||
bitmap-mirror/0002-drive-mirror-add-support-for-conditional-and-always-.patch
|
||||
bitmap-mirror/0003-mirror-add-check-for-bitmap-mode-without-bitmap.patch
|
||||
|
Reference in New Issue
Block a user