rebased pve patches
This commit is contained in:
parent
3c6facff3f
commit
67af0fa481
@ -1,7 +1,7 @@
|
||||
From 926ac2ae6be8a7971e4c24d45345981e3a62d560 Mon Sep 17 00:00:00 2001
|
||||
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
|
||||
Date: Wed, 9 Dec 2015 14:15:49 +0100
|
||||
Subject: [PATCH 01/49] fr-ca keymap corrections
|
||||
Subject: [PATCH 01/28] fr-ca keymap corrections
|
||||
|
||||
---
|
||||
pc-bios/keymaps/fr-ca | 9 +++++++++
|
||||
|
@ -1,7 +1,7 @@
|
||||
From 65a038b874c5770f48077cf77742ac10bb083922 Mon Sep 17 00:00:00 2001
|
||||
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
|
||||
Date: Wed, 9 Dec 2015 14:16:49 +0100
|
||||
Subject: [PATCH 02/49] Adjust network script path to /etc/kvm/
|
||||
Subject: [PATCH 02/28] Adjust network script path to /etc/kvm/
|
||||
|
||||
---
|
||||
include/net/net.h | 5 +++--
|
||||
|
@ -1,7 +1,7 @@
|
||||
From 2d53d7c93802c9c28c5958fae5c71825b1707295 Mon Sep 17 00:00:00 2001
|
||||
From 034ee9d08002e8e57c4d09e9a9750aad547f65f1 Mon Sep 17 00:00:00 2001
|
||||
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
|
||||
Date: Wed, 9 Dec 2015 14:18:46 +0100
|
||||
Subject: [PATCH 04/49] qemu-img: return success on info without snapshots
|
||||
Subject: [PATCH 03/28] qemu-img: return success on info without snapshots
|
||||
|
||||
---
|
||||
qemu-img.c | 3 ++-
|
@ -1,7 +1,7 @@
|
||||
From 1a677a89338980c830ba378824996cd53f2ec96b Mon Sep 17 00:00:00 2001
|
||||
From 0203288ce982ea135ff82cf4ea6a7868ef053470 Mon Sep 17 00:00:00 2001
|
||||
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
|
||||
Date: Wed, 9 Dec 2015 14:27:05 +0100
|
||||
Subject: [PATCH 05/49] use kvm by default
|
||||
Subject: [PATCH 04/28] use kvm by default
|
||||
|
||||
---
|
||||
accel.c | 4 ++--
|
@ -1,7 +1,7 @@
|
||||
From 1cd097140cab2650415b311bd7549036df6e6978 Mon Sep 17 00:00:00 2001
|
||||
From d91355991605106e86f246e0e9091ffc1275b52f Mon Sep 17 00:00:00 2001
|
||||
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
|
||||
Date: Wed, 9 Dec 2015 14:27:49 +0100
|
||||
Subject: [PATCH 06/49] virtio-balloon: fix query
|
||||
Subject: [PATCH 05/28] virtio-balloon: fix query
|
||||
|
||||
Actually provide memory information via the query-balloon
|
||||
command.
|
@ -1,7 +1,7 @@
|
||||
From b5dd9f221abd0afd83f05787ca270c3d80959a2e Mon Sep 17 00:00:00 2001
|
||||
From 99d1d87c126c630afed3885a26b5c4c6ca6e050b Mon Sep 17 00:00:00 2001
|
||||
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
|
||||
Date: Wed, 9 Dec 2015 14:30:21 +0100
|
||||
Subject: [PATCH 07/49] set the CPU model to kvm64/32 instead of qemu64/32
|
||||
Subject: [PATCH 06/28] set the CPU model to kvm64/32 instead of qemu64/32
|
||||
|
||||
---
|
||||
hw/i386/pc.c | 4 ++--
|
@ -1,7 +1,7 @@
|
||||
From 95a583f2d001477eca4c74d49be44f00bf9a8440 Mon Sep 17 00:00:00 2001
|
||||
From a761848c2ded6eb644c0e0e5d9184f54db59828a Mon Sep 17 00:00:00 2001
|
||||
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
|
||||
Date: Wed, 9 Dec 2015 14:31:18 +0100
|
||||
Subject: [PATCH 08/49] qapi: modify query machines
|
||||
Subject: [PATCH 07/28] qapi: modify query machines
|
||||
|
||||
provide '*is-current' in MachineInfo struct
|
||||
---
|
@ -1,7 +1,7 @@
|
||||
From bc5254a21ab6556c000e30fa340d11e0a5bb7dd3 Mon Sep 17 00:00:00 2001
|
||||
From 7215cf5a1ef31a3b0470c16d0b2a3585edf5dbc5 Mon Sep 17 00:00:00 2001
|
||||
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
|
||||
Date: Wed, 9 Dec 2015 14:32:11 +0100
|
||||
Subject: [PATCH 09/49] qapi: modify spice query
|
||||
Subject: [PATCH 08/28] qapi: modify spice query
|
||||
|
||||
Provide the last ticket in the SpiceInfo struct optionally.
|
||||
---
|
@ -1,7 +1,7 @@
|
||||
From 33d16abdcb9d708b9f63c2a5380e4849b9c34fce Mon Sep 17 00:00:00 2001
|
||||
From 3ea2b6f80c46456be2ed339dc2338a61cc7b7bfe Mon Sep 17 00:00:00 2001
|
||||
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
|
||||
Date: Wed, 9 Dec 2015 14:33:34 +0100
|
||||
Subject: [PATCH 10/49] ui/spice: default to pve certs unless otherwise
|
||||
Subject: [PATCH 09/28] ui/spice: default to pve certs unless otherwise
|
||||
specified
|
||||
|
||||
---
|
@ -1,7 +1,7 @@
|
||||
From 4599049cf93b3e189caded4f9bf1dd50c257c927 Mon Sep 17 00:00:00 2001
|
||||
From 1f5a5623052ba8d593e4356f9fda0281e607be76 Mon Sep 17 00:00:00 2001
|
||||
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
|
||||
Date: Wed, 9 Dec 2015 16:04:32 +0100
|
||||
Subject: [PATCH 22/49] internal snapshot async
|
||||
Subject: [PATCH 10/28] internal snapshot async
|
||||
|
||||
---
|
||||
Makefile.objs | 1 +
|
||||
@ -15,16 +15,16 @@ Subject: [PATCH 22/49] internal snapshot async
|
||||
migration/savevm.c | 12 +-
|
||||
qapi-schema.json | 68 +++++++
|
||||
qemu-options.hx | 13 ++
|
||||
savevm-async.c | 525 ++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
savevm-async.c | 523 ++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
vl.c | 8 +
|
||||
13 files changed, 734 insertions(+), 8 deletions(-)
|
||||
13 files changed, 732 insertions(+), 8 deletions(-)
|
||||
create mode 100644 savevm-async.c
|
||||
|
||||
diff --git a/Makefile.objs b/Makefile.objs
|
||||
index 9b12ee6afa..f5f8dbab3b 100644
|
||||
index 6167e7b17d..fbfbbb7f70 100644
|
||||
--- a/Makefile.objs
|
||||
+++ b/Makefile.objs
|
||||
@@ -51,6 +51,7 @@ common-obj-$(CONFIG_LINUX) += fsdev/
|
||||
@@ -50,6 +50,7 @@ common-obj-$(CONFIG_LINUX) += fsdev/
|
||||
|
||||
common-obj-y += migration/
|
||||
common-obj-y += page_cache.o #aio.o
|
||||
@ -46,10 +46,10 @@ index 1fbbb8d606..6ea9ed1c62 100644
|
||||
assert(!bs->job);
|
||||
assert(bdrv_op_blocker_is_empty(bs));
|
||||
diff --git a/hmp-commands-info.hx b/hmp-commands-info.hx
|
||||
index 1a1838099f..3b5a0f95e4 100644
|
||||
index a53f105c52..5fc57a2210 100644
|
||||
--- a/hmp-commands-info.hx
|
||||
+++ b/hmp-commands-info.hx
|
||||
@@ -573,6 +573,19 @@ Show current migration xbzrle cache size.
|
||||
@@ -560,6 +560,19 @@ Show current migration xbzrle cache size.
|
||||
ETEXI
|
||||
|
||||
{
|
||||
@ -70,10 +70,10 @@ index 1a1838099f..3b5a0f95e4 100644
|
||||
.args_type = "",
|
||||
.params = "",
|
||||
diff --git a/hmp-commands.hx b/hmp-commands.hx
|
||||
index 72882039ee..a2867b56f2 100644
|
||||
index 88192817b2..58940a762b 100644
|
||||
--- a/hmp-commands.hx
|
||||
+++ b/hmp-commands.hx
|
||||
@@ -1808,3 +1808,35 @@ ETEXI
|
||||
@@ -1777,3 +1777,35 @@ ETEXI
|
||||
STEXI
|
||||
@end table
|
||||
ETEXI
|
||||
@ -110,10 +110,10 @@ index 72882039ee..a2867b56f2 100644
|
||||
+ .cmd = hmp_savevm_end,
|
||||
+ },
|
||||
diff --git a/hmp.c b/hmp.c
|
||||
index 465d7faad0..aaf0de1642 100644
|
||||
index 904542d026..f725d061e6 100644
|
||||
--- a/hmp.c
|
||||
+++ b/hmp.c
|
||||
@@ -2270,6 +2270,63 @@ void hmp_info_memory_devices(Monitor *mon, const QDict *qdict)
|
||||
@@ -2207,6 +2207,63 @@ void hmp_info_memory_devices(Monitor *mon, const QDict *qdict)
|
||||
qapi_free_MemoryDeviceInfoList(info_list);
|
||||
}
|
||||
|
||||
@ -178,7 +178,7 @@ index 465d7faad0..aaf0de1642 100644
|
||||
{
|
||||
IOThreadInfoList *info_list = qmp_query_iothreads(NULL);
|
||||
diff --git a/hmp.h b/hmp.h
|
||||
index 17a65b2313..8c1b4846b3 100644
|
||||
index 799fd371fa..0497afbf65 100644
|
||||
--- a/hmp.h
|
||||
+++ b/hmp.h
|
||||
@@ -26,6 +26,7 @@ void hmp_info_status(Monitor *mon, const QDict *qdict);
|
||||
@ -189,7 +189,7 @@ index 17a65b2313..8c1b4846b3 100644
|
||||
void hmp_info_migrate(Monitor *mon, const QDict *qdict);
|
||||
void hmp_info_migrate_capabilities(Monitor *mon, const QDict *qdict);
|
||||
void hmp_info_migrate_parameters(Monitor *mon, const QDict *qdict);
|
||||
@@ -95,6 +96,10 @@ void hmp_netdev_add(Monitor *mon, const QDict *qdict);
|
||||
@@ -92,6 +93,10 @@ void hmp_netdev_add(Monitor *mon, const QDict *qdict);
|
||||
void hmp_netdev_del(Monitor *mon, const QDict *qdict);
|
||||
void hmp_getfd(Monitor *mon, const QDict *qdict);
|
||||
void hmp_closefd(Monitor *mon, const QDict *qdict);
|
||||
@ -299,10 +299,10 @@ index 3b19a4a274..feb0dc6834 100644
|
||||
|
||||
/* Give an estimate of the amount left to be transferred,
|
||||
diff --git a/qapi-schema.json b/qapi-schema.json
|
||||
index edb7c32ac9..a25074183c 100644
|
||||
index 1b14ff2476..361700d37c 100644
|
||||
--- a/qapi-schema.json
|
||||
+++ b/qapi-schema.json
|
||||
@@ -813,6 +813,40 @@
|
||||
@@ -723,6 +723,40 @@
|
||||
'*error-desc': 'str'} }
|
||||
|
||||
##
|
||||
@ -343,7 +343,7 @@ index edb7c32ac9..a25074183c 100644
|
||||
# @query-migrate:
|
||||
#
|
||||
# Returns information about current migration process. If migration
|
||||
@@ -4825,9 +4859,43 @@
|
||||
@@ -4735,9 +4769,43 @@
|
||||
#
|
||||
# Since: 1.2.0
|
||||
##
|
||||
@ -413,10 +413,10 @@ index 99af8edf5f..10f0e81f9b 100644
|
||||
"-daemonize daemonize QEMU after initializing\n", QEMU_ARCH_ALL)
|
||||
diff --git a/savevm-async.c b/savevm-async.c
|
||||
new file mode 100644
|
||||
index 0000000000..9704a412d9
|
||||
index 0000000000..2f4766cf6c
|
||||
--- /dev/null
|
||||
+++ b/savevm-async.c
|
||||
@@ -0,0 +1,525 @@
|
||||
@@ -0,0 +1,523 @@
|
||||
+#include "qemu/osdep.h"
|
||||
+#include "qemu-common.h"
|
||||
+#include "qapi/qmp/qerror.h"
|
||||
@ -439,6 +439,8 @@ index 0000000000..9704a412d9
|
||||
+
|
||||
+/* #define DEBUG_SAVEVM_STATE */
|
||||
+
|
||||
+#define NOT_DONE 0x7fffffff /* used while emulated sync operation in progress */
|
||||
+
|
||||
+#ifdef DEBUG_SAVEVM_STATE
|
||||
+#define DPRINTF(fmt, ...) \
|
||||
+ do { printf("savevm-async: " fmt, ## __VA_ARGS__); } while (0)
|
||||
@ -457,7 +459,7 @@ index 0000000000..9704a412d9
|
||||
+
|
||||
+
|
||||
+static struct SnapshotState {
|
||||
+ BlockDriverState *bs;
|
||||
+ BlockBackend *target;
|
||||
+ size_t bs_pos;
|
||||
+ int state;
|
||||
+ Error *error;
|
||||
@ -518,17 +520,17 @@ index 0000000000..9704a412d9
|
||||
+ ret = qemu_fclose(snap_state.file);
|
||||
+ }
|
||||
+
|
||||
+ if (snap_state.bs) {
|
||||
+ if (snap_state.target) {
|
||||
+ /* try to truncate, but ignore errors (will fail on block devices).
|
||||
+ * note: bdrv_read() need whole blocks, so we round up
|
||||
+ */
|
||||
+ size_t size = (snap_state.bs_pos + BDRV_SECTOR_SIZE) & BDRV_SECTOR_MASK;
|
||||
+ bdrv_truncate(snap_state.bs, size);
|
||||
+ bdrv_op_unblock_all(snap_state.bs, snap_state.blocker);
|
||||
+ blk_truncate(snap_state.target, size);
|
||||
+ blk_op_unblock_all(snap_state.target, snap_state.blocker);
|
||||
+ error_free(snap_state.blocker);
|
||||
+ snap_state.blocker = NULL;
|
||||
+ bdrv_unref(snap_state.bs);
|
||||
+ snap_state.bs = NULL;
|
||||
+ blk_unref(snap_state.target);
|
||||
+ snap_state.target = NULL;
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
@ -570,21 +572,22 @@ index 0000000000..9704a412d9
|
||||
+static int block_state_close(void *opaque)
|
||||
+{
|
||||
+ snap_state.file = NULL;
|
||||
+ return bdrv_flush(snap_state.bs);
|
||||
+ return blk_flush(snap_state.target);
|
||||
+}
|
||||
+
|
||||
+static int block_state_put_buffer(void *opaque, const uint8_t *buf,
|
||||
+ int64_t pos, int size)
|
||||
+static ssize_t block_state_writev_buffer(void *opaque, struct iovec *iov,
|
||||
+ int iovcnt, int64_t pos)
|
||||
+{
|
||||
+ int ret;
|
||||
+ QEMUIOVector qiov;
|
||||
+
|
||||
+ assert(pos == snap_state.bs_pos);
|
||||
+
|
||||
+ if ((ret = bdrv_pwrite(snap_state.bs, snap_state.bs_pos, buf, size)) > 0) {
|
||||
+ snap_state.bs_pos += ret;
|
||||
+ }
|
||||
+
|
||||
+ qemu_iovec_init_external(&qiov, iov, iovcnt);
|
||||
+ ret = blk_co_pwritev(snap_state.target, pos, qiov.size, &qiov, 0);
|
||||
+ if (ret < 0) {
|
||||
+ return ret;
|
||||
+ }
|
||||
+ snap_state.bs_pos += qiov.size;
|
||||
+ return qiov.size;
|
||||
+}
|
||||
+
|
||||
+static int store_and_stop(void) {
|
||||
@ -620,12 +623,13 @@ index 0000000000..9704a412d9
|
||||
+ }
|
||||
+
|
||||
+ while (snap_state.state == SAVE_STATE_ACTIVE) {
|
||||
+ uint64_t pending_size;
|
||||
+ uint64_t pending_size, pend_post, pend_nonpost;
|
||||
+
|
||||
+ pending_size = qemu_savevm_state_pending(snap_state.file, 0);
|
||||
+ qemu_savevm_state_pending(snap_state.file, 0, &pend_nonpost, &pend_post);
|
||||
+ pending_size = pend_post + pend_nonpost;
|
||||
+
|
||||
+ if (pending_size) {
|
||||
+ ret = qemu_savevm_state_iterate(snap_state.file);
|
||||
+ ret = qemu_savevm_state_iterate(snap_state.file, false);
|
||||
+ if (ret < 0) {
|
||||
+ save_snapshot_error("qemu_savevm_state_iterate error %d", ret);
|
||||
+ break;
|
||||
@ -636,7 +640,7 @@ index 0000000000..9704a412d9
|
||||
+ if (store_and_stop())
|
||||
+ break;
|
||||
+ DPRINTF("savevm inerate finished\n");
|
||||
+ qemu_savevm_state_complete_precopy(snap_state.file);
|
||||
+ qemu_savevm_state_complete_precopy(snap_state.file, false);
|
||||
+ DPRINTF("save complete\n");
|
||||
+ save_snapshot_completed();
|
||||
+ break;
|
||||
@ -645,7 +649,7 @@ index 0000000000..9704a412d9
|
||||
+ /* stop the VM if we get to the end of available space,
|
||||
+ * or if pending_size is just a few MB
|
||||
+ */
|
||||
+ maxlen = bdrv_getlength(snap_state.bs) - 30*1024*1024;
|
||||
+ maxlen = blk_getlength(snap_state.target) - 30*1024*1024;
|
||||
+ if ((pending_size < 100000) ||
|
||||
+ ((snap_state.bs_pos + pending_size) >= maxlen)) {
|
||||
+ if (store_and_stop())
|
||||
@ -662,18 +666,16 @@ index 0000000000..9704a412d9
|
||||
+}
|
||||
+
|
||||
+static const QEMUFileOps block_file_ops = {
|
||||
+ .put_buffer = block_state_put_buffer,
|
||||
+ .writev_buffer = block_state_writev_buffer,
|
||||
+ .close = block_state_close,
|
||||
+};
|
||||
+
|
||||
+
|
||||
+void qmp_savevm_start(bool has_statefile, const char *statefile, Error **errp)
|
||||
+{
|
||||
+ BlockDriver *drv = NULL;
|
||||
+ Error *local_err = NULL;
|
||||
+
|
||||
+ int bdrv_oflags = BDRV_O_RDWR | BDRV_O_RESIZE;
|
||||
+ int ret;
|
||||
+ int bdrv_oflags = BDRV_O_RDWR | BDRV_O_RESIZE | BDRV_O_NO_FLUSH;
|
||||
+
|
||||
+ if (snap_state.state != SAVE_STATE_DONE) {
|
||||
+ error_set(errp, ERROR_CLASS_GENERIC_ERROR,
|
||||
@ -703,13 +705,11 @@ index 0000000000..9704a412d9
|
||||
+ }
|
||||
+
|
||||
+ /* Open the image */
|
||||
+ snap_state.bs = bdrv_new();
|
||||
+
|
||||
+ QDict *options = NULL;
|
||||
+ options = qdict_new();
|
||||
+ qdict_put(options, "driver", qstring_from_str("raw"));
|
||||
+ ret = bdrv_open(&snap_state.bs, statefile, NULL, options, bdrv_oflags, drv, &local_err);
|
||||
+ if (ret < 0) {
|
||||
+ snap_state.target = blk_new_open(statefile, NULL, options, bdrv_oflags, &local_err);
|
||||
+ if (!snap_state.target) {
|
||||
+ error_set(errp, ERROR_CLASS_GENERIC_ERROR, "failed to open '%s'", statefile);
|
||||
+ goto restart;
|
||||
+ }
|
||||
@ -723,9 +723,9 @@ index 0000000000..9704a412d9
|
||||
+
|
||||
+
|
||||
+ error_setg(&snap_state.blocker, "block device is in use by savevm");
|
||||
+ bdrv_op_block_all(snap_state.bs, snap_state.blocker);
|
||||
+ blk_op_block_all(snap_state.target, snap_state.blocker);
|
||||
+
|
||||
+ Coroutine *co = qemu_coroutine_create(process_savevm_co);
|
||||
+ Coroutine *co = qemu_coroutine_create(process_savevm_co, NULL);
|
||||
+ qemu_coroutine_enter(co);
|
||||
+
|
||||
+ return;
|
||||
@ -873,11 +873,11 @@ index 0000000000..9704a412d9
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static int loadstate_get_buffer(void *opaque, uint8_t *buf, int64_t pos,
|
||||
+ int size)
|
||||
+static ssize_t loadstate_get_buffer(void *opaque, uint8_t *buf, int64_t pos,
|
||||
+ size_t size)
|
||||
+{
|
||||
+ BlockDriverState *bs = (BlockDriverState *)opaque;
|
||||
+ int64_t maxlen = bdrv_getlength(bs);
|
||||
+ BlockBackend *be = opaque;
|
||||
+ int64_t maxlen = blk_getlength(be);
|
||||
+ if (pos > maxlen) {
|
||||
+ return -EIO;
|
||||
+ }
|
||||
@ -887,7 +887,7 @@ index 0000000000..9704a412d9
|
||||
+ if (size == 0) {
|
||||
+ return 0;
|
||||
+ }
|
||||
+ return bdrv_pread(bs, pos, buf, size);
|
||||
+ return blk_pread(be, pos, buf, size);
|
||||
+}
|
||||
+
|
||||
+static const QEMUFileOps loadstate_file_ops = {
|
||||
@ -896,29 +896,27 @@ index 0000000000..9704a412d9
|
||||
+
|
||||
+int load_state_from_blockdev(const char *filename)
|
||||
+{
|
||||
+ BlockDriverState *bs = NULL;
|
||||
+ BlockDriver *drv = NULL;
|
||||
+ BlockBackend *be;
|
||||
+ Error *local_err = NULL;
|
||||
+ Error *blocker = NULL;
|
||||
+
|
||||
+ QEMUFile *f;
|
||||
+ int ret;
|
||||
+ int ret = -EINVAL;
|
||||
+
|
||||
+ bs = bdrv_new();
|
||||
+ ret = bdrv_open(&bs, filename, NULL, NULL, 0, drv, &local_err);
|
||||
+ error_setg(&blocker, "block device is in use by load state");
|
||||
+ bdrv_op_block_all(bs, blocker);
|
||||
+ be = blk_new_open(filename, NULL, NULL, 0, &local_err);
|
||||
+
|
||||
+ if (ret < 0) {
|
||||
+ if (!be) {
|
||||
+ error_report("Could not open VM state file");
|
||||
+ goto the_end;
|
||||
+ }
|
||||
+
|
||||
+ error_setg(&blocker, "block device is in use by load state");
|
||||
+ blk_op_block_all(be, blocker);
|
||||
+
|
||||
+ /* restore the VM state */
|
||||
+ f = qemu_fopen_ops(bs, &loadstate_file_ops);
|
||||
+ f = qemu_fopen_ops(be, &loadstate_file_ops);
|
||||
+ if (!f) {
|
||||
+ error_report("Could not open VM state file");
|
||||
+ ret = -EINVAL;
|
||||
+ goto the_end;
|
||||
+ }
|
||||
+
|
||||
@ -935,10 +933,10 @@ index 0000000000..9704a412d9
|
||||
+ ret = 0;
|
||||
+
|
||||
+ the_end:
|
||||
+ if (bs) {
|
||||
+ bdrv_op_unblock_all(bs, blocker);
|
||||
+ if (be) {
|
||||
+ blk_op_unblock_all(be, blocker);
|
||||
+ error_free(blocker);
|
||||
+ bdrv_unref(bs);
|
||||
+ blk_unref(be);
|
||||
+ }
|
||||
+ return ret;
|
||||
+}
|
@ -1,14 +1,14 @@
|
||||
From c80c9d6e7365d83bae020de4862cc9825374b88c Mon Sep 17 00:00:00 2001
|
||||
From 1a92a719b15ed17e57999e009bc0fb4cf94ef468 Mon Sep 17 00:00:00 2001
|
||||
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
|
||||
Date: Tue, 8 Nov 2016 11:13:06 +0100
|
||||
Subject: [PATCH 46/49] convert savevm-async to threads
|
||||
Subject: [PATCH 11/28] convert savevm-async to threads
|
||||
|
||||
---
|
||||
savevm-async.c | 144 +++++++++++++++++++++++++++++++++++----------------------
|
||||
1 file changed, 88 insertions(+), 56 deletions(-)
|
||||
|
||||
diff --git a/savevm-async.c b/savevm-async.c
|
||||
index 3adf89fdb2..9f839faab5 100644
|
||||
index 2f4766cf6c..624e3a34b4 100644
|
||||
--- a/savevm-async.c
|
||||
+++ b/savevm-async.c
|
||||
@@ -48,6 +48,8 @@ static struct SnapshotState {
|
||||
@ -177,12 +177,12 @@ index 3adf89fdb2..9f839faab5 100644
|
||||
+ ret = global_state_store();
|
||||
+ if (ret) {
|
||||
+ save_snapshot_error("global_state_store error %d", ret);
|
||||
+ break;
|
||||
break;
|
||||
+ }
|
||||
+ ret = vm_stop_force_state(RUN_STATE_FINISH_MIGRATE);
|
||||
+ if (ret < 0) {
|
||||
+ save_snapshot_error("vm_stop_force_state error %d", ret);
|
||||
break;
|
||||
+ break;
|
||||
+ }
|
||||
DPRINTF("savevm inerate finished\n");
|
||||
qemu_savevm_state_complete_precopy(snap_state.file, false);
|
@ -1,7 +1,7 @@
|
||||
From d8699dad1b5941aa0a5a9346f13586366f1fb051 Mon Sep 17 00:00:00 2001
|
||||
From 6c70ffe629c678a110d311fab784d65836a7917e Mon Sep 17 00:00:00 2001
|
||||
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
|
||||
Date: Wed, 9 Dec 2015 16:34:41 +0100
|
||||
Subject: [PATCH 24/49] qmp: add get_link_status
|
||||
Subject: [PATCH 12/28] qmp: add get_link_status
|
||||
|
||||
---
|
||||
net/net.c | 27 +++++++++++++++++++++++++++
|
||||
@ -47,7 +47,7 @@ index 0ac3b9e80c..7410c1e5f3 100644
|
||||
{
|
||||
NetClientState *ncs[MAX_QUEUE_NUM];
|
||||
diff --git a/qapi-schema.json b/qapi-schema.json
|
||||
index a25074183c..21f822aada 100644
|
||||
index 361700d37c..5e82933ca1 100644
|
||||
--- a/qapi-schema.json
|
||||
+++ b/qapi-schema.json
|
||||
@@ -56,6 +56,7 @@
|
||||
@ -58,7 +58,7 @@ index a25074183c..21f822aada 100644
|
||||
'human-monitor-command',
|
||||
'qom-get',
|
||||
'query-migrate-cache-size',
|
||||
@@ -2627,6 +2628,21 @@
|
||||
@@ -2537,6 +2538,21 @@
|
||||
{ 'command': 'set_link', 'data': {'name': 'str', 'up': 'bool'} }
|
||||
|
||||
##
|
321
debian/patches/pve/0012-vma-add-verify-command.patch
vendored
321
debian/patches/pve/0012-vma-add-verify-command.patch
vendored
@ -1,321 +0,0 @@
|
||||
From d4c9597f3064b68853cefca90dd335cd5e5320d0 Mon Sep 17 00:00:00 2001
|
||||
From: Dietmar Maurer <dietmar@proxmox.com>
|
||||
Date: Mon, 11 Mar 2013 07:07:46 +0100
|
||||
Subject: [PATCH 12/49] vma: add verify command
|
||||
|
||||
Users wants to verify the archive after backup.
|
||||
|
||||
Examples:
|
||||
|
||||
# vma verify -v test.vma
|
||||
|
||||
# lzop -d -c test.vma.lzo |vma verify -
|
||||
|
||||
Signed-off-by: Dietmar Maurer <dietmar@proxmox.com>
|
||||
---
|
||||
vma-reader.c | 121 ++++++++++++++++++++++++++++++++++++++++++++---------------
|
||||
vma.c | 55 +++++++++++++++++++++++++++
|
||||
vma.h | 1 +
|
||||
3 files changed, 147 insertions(+), 30 deletions(-)
|
||||
|
||||
diff --git a/vma-reader.c b/vma-reader.c
|
||||
index 51dd8fee0e..2aafb26b2a 100644
|
||||
--- a/vma-reader.c
|
||||
+++ b/vma-reader.c
|
||||
@@ -45,6 +45,8 @@ struct VmaReader {
|
||||
time_t start_time;
|
||||
int64_t cluster_count;
|
||||
int64_t clusters_read;
|
||||
+ int64_t zero_cluster_data;
|
||||
+ int64_t partial_zero_cluster_data;
|
||||
int clusters_read_per;
|
||||
};
|
||||
|
||||
@@ -425,6 +427,27 @@ VmaDeviceInfo *vma_reader_get_device_info(VmaReader *vmar, guint8 dev_id)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+static void allocate_rstate(VmaReader *vmar, guint8 dev_id,
|
||||
+ BlockDriverState *bs, bool write_zeroes)
|
||||
+{
|
||||
+ assert(vmar);
|
||||
+ assert(dev_id);
|
||||
+
|
||||
+ vmar->rstate[dev_id].bs = bs;
|
||||
+ vmar->rstate[dev_id].write_zeroes = write_zeroes;
|
||||
+
|
||||
+ int64_t size = vmar->devinfo[dev_id].size;
|
||||
+
|
||||
+ int64_t bitmap_size = (size/BDRV_SECTOR_SIZE) +
|
||||
+ (VMA_CLUSTER_SIZE/BDRV_SECTOR_SIZE) * BITS_PER_LONG - 1;
|
||||
+ bitmap_size /= (VMA_CLUSTER_SIZE/BDRV_SECTOR_SIZE) * BITS_PER_LONG;
|
||||
+
|
||||
+ vmar->rstate[dev_id].bitmap_size = bitmap_size;
|
||||
+ vmar->rstate[dev_id].bitmap = g_new0(unsigned long, bitmap_size);
|
||||
+
|
||||
+ vmar->cluster_count += size/VMA_CLUSTER_SIZE;
|
||||
+}
|
||||
+
|
||||
int vma_reader_register_bs(VmaReader *vmar, guint8 dev_id, BlockDriverState *bs,
|
||||
bool write_zeroes, Error **errp)
|
||||
{
|
||||
@@ -447,17 +470,7 @@ int vma_reader_register_bs(VmaReader *vmar, guint8 dev_id, BlockDriverState *bs,
|
||||
return -1;
|
||||
}
|
||||
|
||||
- vmar->rstate[dev_id].bs = bs;
|
||||
- vmar->rstate[dev_id].write_zeroes = write_zeroes;
|
||||
-
|
||||
- int64_t bitmap_size = (size/BDRV_SECTOR_SIZE) +
|
||||
- (VMA_CLUSTER_SIZE/BDRV_SECTOR_SIZE) * BITS_PER_LONG - 1;
|
||||
- bitmap_size /= (VMA_CLUSTER_SIZE/BDRV_SECTOR_SIZE) * BITS_PER_LONG;
|
||||
-
|
||||
- vmar->rstate[dev_id].bitmap_size = bitmap_size;
|
||||
- vmar->rstate[dev_id].bitmap = g_new0(unsigned long, bitmap_size);
|
||||
-
|
||||
- vmar->cluster_count += size/VMA_CLUSTER_SIZE;
|
||||
+ allocate_rstate(vmar, dev_id, bs, write_zeroes);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -524,9 +537,10 @@ static int restore_write_data(VmaReader *vmar, guint8 dev_id,
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
+
|
||||
static int restore_extent(VmaReader *vmar, unsigned char *buf,
|
||||
int extent_size, int vmstate_fd,
|
||||
- bool verbose, Error **errp)
|
||||
+ bool verbose, bool verify, Error **errp)
|
||||
{
|
||||
assert(vmar);
|
||||
assert(buf);
|
||||
@@ -551,7 +565,7 @@ static int restore_extent(VmaReader *vmar, unsigned char *buf,
|
||||
|
||||
if (dev_id != vmar->vmstate_stream) {
|
||||
bs = rstate->bs;
|
||||
- if (!bs) {
|
||||
+ if (!verify && !bs) {
|
||||
error_setg(errp, "got wrong dev id %d", dev_id);
|
||||
return -1;
|
||||
}
|
||||
@@ -607,10 +621,13 @@ static int restore_extent(VmaReader *vmar, unsigned char *buf,
|
||||
return -1;
|
||||
}
|
||||
|
||||
- int nb_sectors = end_sector - sector_num;
|
||||
- if (restore_write_data(vmar, dev_id, bs, vmstate_fd, buf + start,
|
||||
- sector_num, nb_sectors, errp) < 0) {
|
||||
- return -1;
|
||||
+ if (!verify) {
|
||||
+ int nb_sectors = end_sector - sector_num;
|
||||
+ if (restore_write_data(vmar, dev_id, bs, vmstate_fd,
|
||||
+ buf + start, sector_num, nb_sectors,
|
||||
+ errp) < 0) {
|
||||
+ return -1;
|
||||
+ }
|
||||
}
|
||||
|
||||
start += VMA_CLUSTER_SIZE;
|
||||
@@ -640,26 +657,37 @@ static int restore_extent(VmaReader *vmar, unsigned char *buf,
|
||||
return -1;
|
||||
}
|
||||
|
||||
- int nb_sectors = end_sector - sector_num;
|
||||
- if (restore_write_data(vmar, dev_id, bs, vmstate_fd,
|
||||
- buf + start, sector_num,
|
||||
- nb_sectors, errp) < 0) {
|
||||
- return -1;
|
||||
+ if (!verify) {
|
||||
+ int nb_sectors = end_sector - sector_num;
|
||||
+ if (restore_write_data(vmar, dev_id, bs, vmstate_fd,
|
||||
+ buf + start, sector_num,
|
||||
+ nb_sectors, errp) < 0) {
|
||||
+ return -1;
|
||||
+ }
|
||||
}
|
||||
|
||||
start += VMA_BLOCK_SIZE;
|
||||
|
||||
} else {
|
||||
|
||||
- if (rstate->write_zeroes && (end_sector > sector_num)) {
|
||||
+
|
||||
+ if (end_sector > sector_num) {
|
||||
/* Todo: use bdrv_co_write_zeroes (but that need to
|
||||
* be run inside coroutine?)
|
||||
*/
|
||||
int nb_sectors = end_sector - sector_num;
|
||||
- if (restore_write_data(vmar, dev_id, bs, vmstate_fd,
|
||||
- zero_vma_block, sector_num,
|
||||
- nb_sectors, errp) < 0) {
|
||||
- return -1;
|
||||
+ int zero_size = BDRV_SECTOR_SIZE*nb_sectors;
|
||||
+ vmar->zero_cluster_data += zero_size;
|
||||
+ if (mask != 0) {
|
||||
+ vmar->partial_zero_cluster_data += zero_size;
|
||||
+ }
|
||||
+
|
||||
+ if (rstate->write_zeroes && !verify) {
|
||||
+ if (restore_write_data(vmar, dev_id, bs, vmstate_fd,
|
||||
+ zero_vma_block, sector_num,
|
||||
+ nb_sectors, errp) < 0) {
|
||||
+ return -1;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -677,8 +705,9 @@ static int restore_extent(VmaReader *vmar, unsigned char *buf,
|
||||
return 0;
|
||||
}
|
||||
|
||||
-int vma_reader_restore(VmaReader *vmar, int vmstate_fd, bool verbose,
|
||||
- Error **errp)
|
||||
+static int vma_reader_restore_full(VmaReader *vmar, int vmstate_fd,
|
||||
+ bool verbose, bool verify,
|
||||
+ Error **errp)
|
||||
{
|
||||
assert(vmar);
|
||||
assert(vmar->head_data);
|
||||
@@ -745,7 +774,7 @@ int vma_reader_restore(VmaReader *vmar, int vmstate_fd, bool verbose,
|
||||
}
|
||||
|
||||
if (restore_extent(vmar, buf, extent_size, vmstate_fd, verbose,
|
||||
- errp) < 0) {
|
||||
+ verify, errp) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -792,6 +821,38 @@ int vma_reader_restore(VmaReader *vmar, int vmstate_fd, bool verbose,
|
||||
}
|
||||
}
|
||||
|
||||
+ if (verbose) {
|
||||
+ printf("total bytes read %zd, sparse bytes %zd (%.3g%%)\n",
|
||||
+ vmar->clusters_read*VMA_CLUSTER_SIZE,
|
||||
+ vmar->zero_cluster_data,
|
||||
+ (double)(100.0*vmar->zero_cluster_data)/
|
||||
+ (vmar->clusters_read*VMA_CLUSTER_SIZE));
|
||||
+
|
||||
+ int64_t datasize = vmar->clusters_read*VMA_CLUSTER_SIZE-vmar->zero_cluster_data;
|
||||
+ if (datasize) { // this does not make sense for empty files
|
||||
+ printf("space reduction due to 4K zero blocks %.3g%%\n",
|
||||
+ (double)(100.0*vmar->partial_zero_cluster_data) / datasize);
|
||||
+ }
|
||||
+ }
|
||||
return ret;
|
||||
}
|
||||
|
||||
+int vma_reader_restore(VmaReader *vmar, int vmstate_fd, bool verbose,
|
||||
+ Error **errp)
|
||||
+{
|
||||
+ return vma_reader_restore_full(vmar, vmstate_fd, verbose, false, errp);
|
||||
+}
|
||||
+
|
||||
+int vma_reader_verify(VmaReader *vmar, bool verbose, Error **errp)
|
||||
+{
|
||||
+ guint8 dev_id;
|
||||
+
|
||||
+ for (dev_id = 1; dev_id < 255; dev_id++) {
|
||||
+ if (vma_reader_get_device_info(vmar, dev_id)) {
|
||||
+ allocate_rstate(vmar, dev_id, NULL, false);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return vma_reader_restore_full(vmar, -1, verbose, true, errp);
|
||||
+}
|
||||
+
|
||||
diff --git a/vma.c b/vma.c
|
||||
index 8732bfa85e..ab7b766014 100644
|
||||
--- a/vma.c
|
||||
+++ b/vma.c
|
||||
@@ -29,6 +29,7 @@ static void help(void)
|
||||
"vma list <filename>\n"
|
||||
"vma create <filename> [-c config] <archive> pathname ...\n"
|
||||
"vma extract <filename> [-r <fifo>] <targetdir>\n"
|
||||
+ "vma verify <filename> [-v]\n"
|
||||
;
|
||||
|
||||
printf("%s", help_msg);
|
||||
@@ -333,6 +334,58 @@ static int extract_content(int argc, char **argv)
|
||||
return ret;
|
||||
}
|
||||
|
||||
+static int verify_content(int argc, char **argv)
|
||||
+{
|
||||
+ int c, ret = 0;
|
||||
+ int verbose = 0;
|
||||
+ const char *filename;
|
||||
+
|
||||
+ for (;;) {
|
||||
+ c = getopt(argc, argv, "hv");
|
||||
+ if (c == -1) {
|
||||
+ break;
|
||||
+ }
|
||||
+ switch (c) {
|
||||
+ case '?':
|
||||
+ case 'h':
|
||||
+ help();
|
||||
+ break;
|
||||
+ case 'v':
|
||||
+ verbose = 1;
|
||||
+ break;
|
||||
+ default:
|
||||
+ help();
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* Get the filename */
|
||||
+ if ((optind + 1) != argc) {
|
||||
+ help();
|
||||
+ }
|
||||
+ filename = argv[optind++];
|
||||
+
|
||||
+ Error *errp = NULL;
|
||||
+ VmaReader *vmar = vma_reader_create(filename, &errp);
|
||||
+
|
||||
+ if (!vmar) {
|
||||
+ g_error("%s", error_get_pretty(errp));
|
||||
+ }
|
||||
+
|
||||
+ if (verbose) {
|
||||
+ print_content(vmar);
|
||||
+ }
|
||||
+
|
||||
+ if (vma_reader_verify(vmar, verbose, &errp) < 0) {
|
||||
+ g_error("verify failed - %s", error_get_pretty(errp));
|
||||
+ }
|
||||
+
|
||||
+ vma_reader_destroy(vmar);
|
||||
+
|
||||
+ bdrv_close_all();
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
typedef struct BackupJob {
|
||||
BlockDriverState *bs;
|
||||
int64_t len;
|
||||
@@ -579,6 +632,8 @@ int main(int argc, char **argv)
|
||||
return create_archive(argc, argv);
|
||||
} else if (!strcmp(cmdname, "extract")) {
|
||||
return extract_content(argc, argv);
|
||||
+ } else if (!strcmp(cmdname, "verify")) {
|
||||
+ return verify_content(argc, argv);
|
||||
}
|
||||
|
||||
help();
|
||||
diff --git a/vma.h b/vma.h
|
||||
index 6625eb95c6..9bb6ea4f69 100644
|
||||
--- a/vma.h
|
||||
+++ b/vma.h
|
||||
@@ -142,5 +142,6 @@ int vma_reader_register_bs(VmaReader *vmar, guint8 dev_id,
|
||||
Error **errp);
|
||||
int vma_reader_restore(VmaReader *vmar, int vmstate_fd, bool verbose,
|
||||
Error **errp);
|
||||
+int vma_reader_verify(VmaReader *vmar, bool verbose, Error **errp);
|
||||
|
||||
#endif /* BACKUP_VMA_H */
|
||||
--
|
||||
2.11.0
|
||||
|
@ -1,7 +1,7 @@
|
||||
From 2d50e3a3e1eecb40c4935ee6c5808a823ae79440 Mon Sep 17 00:00:00 2001
|
||||
From 3afb3d14378cc401e37dafd8437cfc45cce2aaea Mon Sep 17 00:00:00 2001
|
||||
From: Alexandre Derumier <aderumier@odiso.com>
|
||||
Date: Tue, 29 Sep 2015 15:37:44 +0200
|
||||
Subject: [PATCH 25/49] smm_available = false
|
||||
Subject: [PATCH 13/28] smm_available = false
|
||||
|
||||
Signed-off-by: Alexandre Derumier <aderumier@odiso.com>
|
||||
---
|
@ -1,101 +0,0 @@
|
||||
From 7462043311f01c05c98a1f60f696ac4b465a7f38 Mon Sep 17 00:00:00 2001
|
||||
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
|
||||
Date: Wed, 9 Dec 2015 14:46:49 +0100
|
||||
Subject: [PATCH 13/49] vma: add 'config' command to dump the config
|
||||
|
||||
---
|
||||
vma.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 64 insertions(+)
|
||||
|
||||
diff --git a/vma.c b/vma.c
|
||||
index ab7b766014..89254070c4 100644
|
||||
--- a/vma.c
|
||||
+++ b/vma.c
|
||||
@@ -27,6 +27,7 @@ static void help(void)
|
||||
"usage: vma command [command options]\n"
|
||||
"\n"
|
||||
"vma list <filename>\n"
|
||||
+ "vma config <filename> [-c config]\n"
|
||||
"vma create <filename> [-c config] <archive> pathname ...\n"
|
||||
"vma extract <filename> [-r <fifo>] <targetdir>\n"
|
||||
"vma verify <filename> [-v]\n"
|
||||
@@ -605,6 +606,67 @@ static int create_archive(int argc, char **argv)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int dump_config(int argc, char **argv)
|
||||
+{
|
||||
+ int c, ret = 0;
|
||||
+ const char *filename;
|
||||
+ const char *config_name = "qemu-server.conf";
|
||||
+
|
||||
+ for (;;) {
|
||||
+ c = getopt(argc, argv, "hc:");
|
||||
+ if (c == -1) {
|
||||
+ break;
|
||||
+ }
|
||||
+ switch (c) {
|
||||
+ case '?':
|
||||
+ case 'h':
|
||||
+ help();
|
||||
+ break;
|
||||
+ case 'c':
|
||||
+ config_name = optarg;
|
||||
+ break;
|
||||
+ default:
|
||||
+ help();
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* Get the filename */
|
||||
+ if ((optind + 1) != argc) {
|
||||
+ help();
|
||||
+ }
|
||||
+ filename = argv[optind++];
|
||||
+
|
||||
+ Error *errp = NULL;
|
||||
+ VmaReader *vmar = vma_reader_create(filename, &errp);
|
||||
+
|
||||
+ if (!vmar) {
|
||||
+ g_error("%s", error_get_pretty(errp));
|
||||
+ }
|
||||
+
|
||||
+ int found = 0;
|
||||
+ GList *l = vma_reader_get_config_data(vmar);
|
||||
+ while (l && l->data) {
|
||||
+ VmaConfigData *cdata = (VmaConfigData *)l->data;
|
||||
+ l = g_list_next(l);
|
||||
+ if (strcmp(cdata->name, config_name) == 0) {
|
||||
+ found = 1;
|
||||
+ fwrite(cdata->data, cdata->len, 1, stdout);
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ vma_reader_destroy(vmar);
|
||||
+
|
||||
+ bdrv_close_all();
|
||||
+
|
||||
+ if (!found) {
|
||||
+ fprintf(stderr, "unable to find configuration data '%s'\n", config_name);
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const char *cmdname;
|
||||
@@ -634,6 +696,8 @@ int main(int argc, char **argv)
|
||||
return extract_content(argc, argv);
|
||||
} else if (!strcmp(cmdname, "verify")) {
|
||||
return verify_content(argc, argv);
|
||||
+ } else if (!strcmp(cmdname, "config")) {
|
||||
+ return dump_config(argc, argv);
|
||||
}
|
||||
|
||||
help();
|
||||
--
|
||||
2.11.0
|
||||
|
292
debian/patches/pve/0014-backup-modify-job-api.patch
vendored
292
debian/patches/pve/0014-backup-modify-job-api.patch
vendored
@ -1,292 +0,0 @@
|
||||
From 18f7a9b94a81e794c66e6e9d1ca7a9dafb1d17cb Mon Sep 17 00:00:00 2001
|
||||
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
|
||||
Date: Wed, 9 Dec 2015 15:04:57 +0100
|
||||
Subject: [PATCH 14/49] backup: modify job api
|
||||
|
||||
Introduces a BackupDump function callback and a pause_count
|
||||
for backup_start. For a dump-backup the target parameter
|
||||
can now be NULL so access to target needs to be guarded now.
|
||||
---
|
||||
block/backup.c | 118 +++++++++++++++++++++++++++++-----------------
|
||||
block/replication.c | 3 +-
|
||||
blockdev.c | 4 +-
|
||||
include/block/block_int.h | 5 ++
|
||||
4 files changed, 83 insertions(+), 47 deletions(-)
|
||||
|
||||
diff --git a/block/backup.c b/block/backup.c
|
||||
index a4fb2884f9..fe4ce7f504 100644
|
||||
--- a/block/backup.c
|
||||
+++ b/block/backup.c
|
||||
@@ -36,6 +36,7 @@ typedef struct BackupBlockJob {
|
||||
BdrvDirtyBitmap *sync_bitmap;
|
||||
MirrorSyncMode sync_mode;
|
||||
RateLimit limit;
|
||||
+ BackupDumpFunc *dump_cb;
|
||||
BlockdevOnError on_source_error;
|
||||
BlockdevOnError on_target_error;
|
||||
CoRwlock flush_rwlock;
|
||||
@@ -145,13 +146,24 @@ static int coroutine_fn backup_do_cow(BackupBlockJob *job,
|
||||
goto out;
|
||||
}
|
||||
|
||||
+ int64_t start_sec = start * sectors_per_cluster;
|
||||
if (buffer_is_zero(iov.iov_base, iov.iov_len)) {
|
||||
- ret = blk_co_pwrite_zeroes(job->target, start * job->cluster_size,
|
||||
- bounce_qiov.size, BDRV_REQ_MAY_UNMAP);
|
||||
+ if (job->dump_cb) {
|
||||
+ ret = job->dump_cb(job->common.opaque, job->target, start_sec, n, NULL);
|
||||
+ }
|
||||
+ if (job->target) {
|
||||
+ ret = blk_co_pwrite_zeroes(job->target, start * job->cluster_size,
|
||||
+ bounce_qiov.size, BDRV_REQ_MAY_UNMAP);
|
||||
+ }
|
||||
} else {
|
||||
- ret = blk_co_pwritev(job->target, start * job->cluster_size,
|
||||
- bounce_qiov.size, &bounce_qiov,
|
||||
- job->compress ? BDRV_REQ_WRITE_COMPRESSED : 0);
|
||||
+ if (job->dump_cb) {
|
||||
+ ret = job->dump_cb(job->common.opaque, job->target, start_sec, n, bounce_buffer);
|
||||
+ }
|
||||
+ if (job->target) {
|
||||
+ ret = blk_co_pwritev(job->target, start * job->cluster_size,
|
||||
+ bounce_qiov.size, &bounce_qiov,
|
||||
+ job->compress ? BDRV_REQ_WRITE_COMPRESSED : 0);
|
||||
+ }
|
||||
}
|
||||
if (ret < 0) {
|
||||
trace_backup_do_cow_write_fail(job, start, ret);
|
||||
@@ -246,6 +258,8 @@ static void backup_abort(BlockJob *job)
|
||||
static void backup_clean(BlockJob *job)
|
||||
{
|
||||
BackupBlockJob *s = container_of(job, BackupBlockJob, common);
|
||||
+ if (!s->target)
|
||||
+ return;
|
||||
assert(s->target);
|
||||
blk_unref(s->target);
|
||||
s->target = NULL;
|
||||
@@ -330,9 +344,11 @@ static BlockErrorAction backup_error_action(BackupBlockJob *job,
|
||||
if (read) {
|
||||
return block_job_error_action(&job->common, job->on_source_error,
|
||||
true, error);
|
||||
- } else {
|
||||
+ } else if (job->target) {
|
||||
return block_job_error_action(&job->common, job->on_target_error,
|
||||
false, error);
|
||||
+ } else {
|
||||
+ return BLOCK_ERROR_ACTION_REPORT;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -453,6 +469,7 @@ static void coroutine_fn backup_run(void *opaque)
|
||||
|
||||
job->done_bitmap = bitmap_new(end);
|
||||
|
||||
+
|
||||
job->before_write.notify = backup_before_write_notify;
|
||||
bdrv_add_before_write_notifier(bs, &job->before_write);
|
||||
|
||||
@@ -557,7 +574,9 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
|
||||
BlockdevOnError on_source_error,
|
||||
BlockdevOnError on_target_error,
|
||||
int creation_flags,
|
||||
+ BackupDumpFunc *dump_cb,
|
||||
BlockCompletionFunc *cb, void *opaque,
|
||||
+ int pause_count,
|
||||
BlockJobTxn *txn, Error **errp)
|
||||
{
|
||||
int64_t len;
|
||||
@@ -566,7 +585,7 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
|
||||
int ret;
|
||||
|
||||
assert(bs);
|
||||
- assert(target);
|
||||
+ assert(target || dump_cb);
|
||||
|
||||
if (bs == target) {
|
||||
error_setg(errp, "Source and target cannot be the same");
|
||||
@@ -579,13 +598,13 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
- if (!bdrv_is_inserted(target)) {
|
||||
+ if (target && !bdrv_is_inserted(target)) {
|
||||
error_setg(errp, "Device is not inserted: %s",
|
||||
bdrv_get_device_name(target));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
- if (compress && target->drv->bdrv_co_pwritev_compressed == NULL) {
|
||||
+ if (target && compress && target->drv->bdrv_co_pwritev_compressed == NULL) {
|
||||
error_setg(errp, "Compression is not supported for this drive %s",
|
||||
bdrv_get_device_name(target));
|
||||
return NULL;
|
||||
@@ -595,7 +614,7 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
- if (bdrv_op_is_blocked(target, BLOCK_OP_TYPE_BACKUP_TARGET, errp)) {
|
||||
+ if (target && bdrv_op_is_blocked(target, BLOCK_OP_TYPE_BACKUP_TARGET, errp)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -635,15 +654,18 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
|
||||
goto error;
|
||||
}
|
||||
|
||||
- /* The target must match the source in size, so no resize here either */
|
||||
- job->target = blk_new(BLK_PERM_WRITE,
|
||||
- BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE |
|
||||
- BLK_PERM_WRITE_UNCHANGED | BLK_PERM_GRAPH_MOD);
|
||||
- ret = blk_insert_bs(job->target, target, errp);
|
||||
- if (ret < 0) {
|
||||
- goto error;
|
||||
+ if (target) {
|
||||
+ /* The target must match the source in size, so no resize here either */
|
||||
+ job->target = blk_new(BLK_PERM_WRITE,
|
||||
+ BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE |
|
||||
+ BLK_PERM_WRITE_UNCHANGED | BLK_PERM_GRAPH_MOD);
|
||||
+ ret = blk_insert_bs(job->target, target, errp);
|
||||
+ if (ret < 0) {
|
||||
+ goto error;
|
||||
+ }
|
||||
}
|
||||
|
||||
+ job->dump_cb = dump_cb;
|
||||
job->on_source_error = on_source_error;
|
||||
job->on_target_error = on_target_error;
|
||||
job->sync_mode = sync_mode;
|
||||
@@ -651,36 +673,44 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
|
||||
sync_bitmap : NULL;
|
||||
job->compress = compress;
|
||||
|
||||
- /* If there is no backing file on the target, we cannot rely on COW if our
|
||||
- * backup cluster size is smaller than the target cluster size. Even for
|
||||
- * targets with a backing file, try to avoid COW if possible. */
|
||||
- ret = bdrv_get_info(target, &bdi);
|
||||
- if (ret == -ENOTSUP && !target->backing) {
|
||||
- /* Cluster size is not defined */
|
||||
- error_report("WARNING: The target block device doesn't provide "
|
||||
- "information about the block size and it doesn't have a "
|
||||
- "backing file. The default block size of %u bytes is "
|
||||
- "used. If the actual block size of the target exceeds "
|
||||
- "this default, the backup may be unusable",
|
||||
- BACKUP_CLUSTER_SIZE_DEFAULT);
|
||||
- job->cluster_size = BACKUP_CLUSTER_SIZE_DEFAULT;
|
||||
- } else if (ret < 0 && !target->backing) {
|
||||
- error_setg_errno(errp, -ret,
|
||||
- "Couldn't determine the cluster size of the target image, "
|
||||
- "which has no backing file");
|
||||
- error_append_hint(errp,
|
||||
- "Aborting, since this may create an unusable destination image\n");
|
||||
- goto error;
|
||||
- } else if (ret < 0 && target->backing) {
|
||||
- /* Not fatal; just trudge on ahead. */
|
||||
- job->cluster_size = BACKUP_CLUSTER_SIZE_DEFAULT;
|
||||
+ if (target) {
|
||||
+ /* If there is no backing file on the target, we cannot rely on COW if our
|
||||
+ * backup cluster size is smaller than the target cluster size. Even for
|
||||
+ * targets with a backing file, try to avoid COW if possible. */
|
||||
+ ret = bdrv_get_info(target, &bdi);
|
||||
+ if (ret == -ENOTSUP && !target->backing) {
|
||||
+ /* Cluster size is not defined */
|
||||
+ error_report("WARNING: The target block device doesn't provide "
|
||||
+ "information about the block size and it doesn't have a "
|
||||
+ "backing file. The default block size of %u bytes is "
|
||||
+ "used. If the actual block size of the target exceeds "
|
||||
+ "this default, the backup may be unusable",
|
||||
+ BACKUP_CLUSTER_SIZE_DEFAULT);
|
||||
+ job->cluster_size = BACKUP_CLUSTER_SIZE_DEFAULT;
|
||||
+ } else if (ret < 0 && !target->backing) {
|
||||
+ error_setg_errno(errp, -ret,
|
||||
+ "Couldn't determine the cluster size of the target image, "
|
||||
+ "which has no backing file");
|
||||
+ error_append_hint(errp,
|
||||
+ "Aborting, since this may create an unusable destination image\n");
|
||||
+ goto error;
|
||||
+ } else if (ret < 0 && target->backing) {
|
||||
+ /* Not fatal; just trudge on ahead. */
|
||||
+ job->cluster_size = BACKUP_CLUSTER_SIZE_DEFAULT;
|
||||
+ } else {
|
||||
+ job->cluster_size = BACKUP_CLUSTER_SIZE_DEFAULT;
|
||||
+ }
|
||||
} else {
|
||||
- job->cluster_size = MAX(BACKUP_CLUSTER_SIZE_DEFAULT, bdi.cluster_size);
|
||||
+ job->cluster_size = BACKUP_CLUSTER_SIZE_DEFAULT;
|
||||
}
|
||||
|
||||
- /* Required permissions are already taken with target's blk_new() */
|
||||
- block_job_add_bdrv(&job->common, "target", target, 0, BLK_PERM_ALL,
|
||||
- &error_abort);
|
||||
+ if (target) {
|
||||
+ /* Required permissions are already taken with target's blk_new() */
|
||||
+ block_job_add_bdrv(&job->common, "target", target, 0, BLK_PERM_ALL,
|
||||
+ &error_abort);
|
||||
+ } else {
|
||||
+ job->common.pause_count = pause_count;
|
||||
+ }
|
||||
job->common.len = len;
|
||||
block_job_txn_add_job(txn, &job->common);
|
||||
|
||||
diff --git a/block/replication.c b/block/replication.c
|
||||
index bf3c395eb4..60c6524417 100644
|
||||
--- a/block/replication.c
|
||||
+++ b/block/replication.c
|
||||
@@ -531,7 +531,8 @@ static void replication_start(ReplicationState *rs, ReplicationMode mode,
|
||||
0, MIRROR_SYNC_MODE_NONE, NULL, false,
|
||||
BLOCKDEV_ON_ERROR_REPORT,
|
||||
BLOCKDEV_ON_ERROR_REPORT, BLOCK_JOB_INTERNAL,
|
||||
- backup_job_completed, bs, NULL, &local_err);
|
||||
+ NULL,
|
||||
+ backup_job_completed, bs, 0, NULL, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
backup_job_cleanup(bs);
|
||||
diff --git a/blockdev.c b/blockdev.c
|
||||
index 4927914ce3..5ddd363a33 100644
|
||||
--- a/blockdev.c
|
||||
+++ b/blockdev.c
|
||||
@@ -3273,7 +3273,7 @@ static BlockJob *do_drive_backup(DriveBackup *backup, BlockJobTxn *txn,
|
||||
job = backup_job_create(backup->job_id, bs, target_bs, backup->speed,
|
||||
backup->sync, bmap, backup->compress,
|
||||
backup->on_source_error, backup->on_target_error,
|
||||
- BLOCK_JOB_DEFAULT, NULL, NULL, txn, &local_err);
|
||||
+ BLOCK_JOB_DEFAULT, NULL, NULL, NULL, 0, txn, &local_err);
|
||||
bdrv_unref(target_bs);
|
||||
if (local_err != NULL) {
|
||||
error_propagate(errp, local_err);
|
||||
@@ -3352,7 +3352,7 @@ BlockJob *do_blockdev_backup(BlockdevBackup *backup, BlockJobTxn *txn,
|
||||
job = backup_job_create(backup->job_id, bs, target_bs, backup->speed,
|
||||
backup->sync, NULL, backup->compress,
|
||||
backup->on_source_error, backup->on_target_error,
|
||||
- BLOCK_JOB_DEFAULT, NULL, NULL, txn, &local_err);
|
||||
+ BLOCK_JOB_DEFAULT, NULL, NULL, NULL, 0, txn, &local_err);
|
||||
if (local_err != NULL) {
|
||||
error_propagate(errp, local_err);
|
||||
}
|
||||
diff --git a/include/block/block_int.h b/include/block/block_int.h
|
||||
index 59400bd848..ec655815ca 100644
|
||||
--- a/include/block/block_int.h
|
||||
+++ b/include/block/block_int.h
|
||||
@@ -59,6 +59,9 @@
|
||||
|
||||
#define BLOCK_PROBE_BUF_SIZE 512
|
||||
|
||||
+typedef int BackupDumpFunc(void *opaque, BlockDriverState *bs,
|
||||
+ int64_t sector_num, int n_sectors, unsigned char *buf);
|
||||
+
|
||||
enum BdrvTrackedRequestType {
|
||||
BDRV_TRACKED_READ,
|
||||
BDRV_TRACKED_WRITE,
|
||||
@@ -877,7 +880,9 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
|
||||
BlockdevOnError on_source_error,
|
||||
BlockdevOnError on_target_error,
|
||||
int creation_flags,
|
||||
+ BackupDumpFunc *dump_cb,
|
||||
BlockCompletionFunc *cb, void *opaque,
|
||||
+ int pause_count,
|
||||
BlockJobTxn *txn, Error **errp);
|
||||
|
||||
void hmp_drive_add_node(Monitor *mon, const char *optstr);
|
||||
--
|
||||
2.11.0
|
||||
|
@ -1,7 +1,7 @@
|
||||
From 907dfd6792ab3e5030c859e1bd857f0127515e5c Mon Sep 17 00:00:00 2001
|
||||
From 8f6787a80cafc259d2247a294ea657aee0928488 Mon Sep 17 00:00:00 2001
|
||||
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
|
||||
Date: Wed, 9 Dec 2015 16:50:05 +0100
|
||||
Subject: [PATCH 26/49] use whitespace between VERSION and PKGVERSION
|
||||
Subject: [PATCH 14/28] use whitespace between VERSION and PKGVERSION
|
||||
|
||||
Our kvm version parser expects a white space or comma after
|
||||
the version string, see PVE::QemuServer::kvm_user_version()
|
@ -1,830 +0,0 @@
|
||||
From 4919cc7182665534c0ba82203b10a6ead1d41d03 Mon Sep 17 00:00:00 2001
|
||||
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
|
||||
Date: Wed, 9 Dec 2015 15:20:56 +0100
|
||||
Subject: [PATCH 15/49] backup: add pve monitor commands
|
||||
|
||||
---
|
||||
blockdev.c | 465 ++++++++++++++++++++++++++++++++++++++++++++++
|
||||
blockjob.c | 11 +-
|
||||
hmp-commands-info.hx | 13 ++
|
||||
hmp-commands.hx | 29 +++
|
||||
hmp.c | 61 ++++++
|
||||
hmp.h | 3 +
|
||||
include/block/block_int.h | 2 +-
|
||||
qapi-schema.json | 90 +++++++++
|
||||
8 files changed, 668 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/blockdev.c b/blockdev.c
|
||||
index 5ddd363a33..58cf5d3c80 100644
|
||||
--- a/blockdev.c
|
||||
+++ b/blockdev.c
|
||||
@@ -35,6 +35,7 @@
|
||||
#include "sysemu/blockdev.h"
|
||||
#include "hw/block/block.h"
|
||||
#include "block/blockjob.h"
|
||||
+#include "block/blockjob_int.h"
|
||||
#include "block/throttle-groups.h"
|
||||
#include "monitor/monitor.h"
|
||||
#include "qemu/error-report.h"
|
||||
@@ -53,6 +54,7 @@
|
||||
#include "qemu/cutils.h"
|
||||
#include "qemu/help_option.h"
|
||||
#include "qemu/throttle-options.h"
|
||||
+#include "vma.h"
|
||||
|
||||
static QTAILQ_HEAD(, BlockDriverState) monitor_bdrv_states =
|
||||
QTAILQ_HEAD_INITIALIZER(monitor_bdrv_states);
|
||||
@@ -2956,6 +2958,469 @@ out:
|
||||
aio_context_release(aio_context);
|
||||
}
|
||||
|
||||
+void block_job_event_cancelled(BlockJob *job);
|
||||
+void block_job_event_completed(BlockJob *job, const char *msg);
|
||||
+static void block_job_cb(void *opaque, int ret)
|
||||
+{
|
||||
+ /* Note that this function may be executed from another AioContext besides
|
||||
+ * the QEMU main loop. If you need to access anything that assumes the
|
||||
+ * QEMU global mutex, use a BH or introduce a mutex.
|
||||
+ */
|
||||
+
|
||||
+ BlockDriverState *bs = opaque;
|
||||
+ const char *msg = NULL;
|
||||
+
|
||||
+ assert(bs->job);
|
||||
+
|
||||
+ if (ret < 0) {
|
||||
+ msg = strerror(-ret);
|
||||
+ }
|
||||
+
|
||||
+ if (block_job_is_cancelled(bs->job)) {
|
||||
+ block_job_event_cancelled(bs->job);
|
||||
+ } else {
|
||||
+ block_job_event_completed(bs->job, msg);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/* PVE backup related function */
|
||||
+
|
||||
+static struct PVEBackupState {
|
||||
+ Error *error;
|
||||
+ bool cancel;
|
||||
+ uuid_t uuid;
|
||||
+ char uuid_str[37];
|
||||
+ int64_t speed;
|
||||
+ time_t start_time;
|
||||
+ time_t end_time;
|
||||
+ char *backup_file;
|
||||
+ VmaWriter *vmaw;
|
||||
+ GList *di_list;
|
||||
+ size_t total;
|
||||
+ size_t transferred;
|
||||
+ size_t zero_bytes;
|
||||
+} backup_state;
|
||||
+
|
||||
+typedef struct PVEBackupDevInfo {
|
||||
+ BlockDriverState *bs;
|
||||
+ size_t size;
|
||||
+ uint8_t dev_id;
|
||||
+ //bool started;
|
||||
+ bool completed;
|
||||
+} PVEBackupDevInfo;
|
||||
+
|
||||
+static void pvebackup_run_next_job(void);
|
||||
+
|
||||
+static int pvebackup_dump_cb(void *opaque, BlockBackend *target,
|
||||
+ int64_t sector_num, int n_sectors,
|
||||
+ unsigned char *buf)
|
||||
+{
|
||||
+ PVEBackupDevInfo *di = opaque;
|
||||
+
|
||||
+ if (sector_num & 0x7f) {
|
||||
+ if (!backup_state.error) {
|
||||
+ error_setg(&backup_state.error,
|
||||
+ "got unaligned write inside backup dump "
|
||||
+ "callback (sector %ld)", sector_num);
|
||||
+ }
|
||||
+ return -1; // not aligned to cluster size
|
||||
+ }
|
||||
+
|
||||
+ int64_t cluster_num = sector_num >> 7;
|
||||
+ int size = n_sectors * BDRV_SECTOR_SIZE;
|
||||
+
|
||||
+ int ret = -1;
|
||||
+
|
||||
+ if (backup_state.vmaw) {
|
||||
+ size_t zero_bytes = 0;
|
||||
+ ret = vma_writer_write(backup_state.vmaw, di->dev_id, cluster_num,
|
||||
+ buf, &zero_bytes);
|
||||
+ backup_state.zero_bytes += zero_bytes;
|
||||
+ } else {
|
||||
+ ret = size;
|
||||
+ if (!buf) {
|
||||
+ backup_state.zero_bytes += size;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ backup_state.transferred += size;
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static void pvebackup_cleanup(void)
|
||||
+{
|
||||
+ backup_state.end_time = time(NULL);
|
||||
+
|
||||
+ if (backup_state.vmaw) {
|
||||
+ Error *local_err = NULL;
|
||||
+ vma_writer_close(backup_state.vmaw, &local_err);
|
||||
+ error_propagate(&backup_state.error, local_err);
|
||||
+ backup_state.vmaw = NULL;
|
||||
+ }
|
||||
+
|
||||
+ if (backup_state.di_list) {
|
||||
+ GList *l = backup_state.di_list;
|
||||
+ while (l) {
|
||||
+ PVEBackupDevInfo *di = (PVEBackupDevInfo *)l->data;
|
||||
+ l = g_list_next(l);
|
||||
+ g_free(di);
|
||||
+ }
|
||||
+ g_list_free(backup_state.di_list);
|
||||
+ backup_state.di_list = NULL;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void pvebackup_complete_cb(void *opaque, int ret)
|
||||
+{
|
||||
+ PVEBackupDevInfo *di = opaque;
|
||||
+
|
||||
+ assert(backup_state.vmaw);
|
||||
+
|
||||
+ di->completed = true;
|
||||
+
|
||||
+ if (ret < 0 && !backup_state.error) {
|
||||
+ error_setg(&backup_state.error, "job failed with err %d - %s",
|
||||
+ ret, strerror(-ret));
|
||||
+ }
|
||||
+
|
||||
+ BlockDriverState *bs = di->bs;
|
||||
+
|
||||
+ di->bs = NULL;
|
||||
+
|
||||
+ vma_writer_close_stream(backup_state.vmaw, di->dev_id);
|
||||
+
|
||||
+ block_job_cb(bs, ret);
|
||||
+
|
||||
+ if (!backup_state.cancel) {
|
||||
+ pvebackup_run_next_job();
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void pvebackup_cancel(void *opaque)
|
||||
+{
|
||||
+ backup_state.cancel = true;
|
||||
+
|
||||
+ if (!backup_state.error) {
|
||||
+ error_setg(&backup_state.error, "backup cancelled");
|
||||
+ }
|
||||
+
|
||||
+ /* drain all i/o (awake jobs waiting for aio) */
|
||||
+ bdrv_drain_all();
|
||||
+
|
||||
+ GList *l = backup_state.di_list;
|
||||
+ while (l) {
|
||||
+ PVEBackupDevInfo *di = (PVEBackupDevInfo *)l->data;
|
||||
+ l = g_list_next(l);
|
||||
+ if (!di->completed && di->bs) {
|
||||
+ BlockJob *job = di->bs->job;
|
||||
+ if (job) {
|
||||
+ if (!di->completed) {
|
||||
+ block_job_cancel_sync(job);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ pvebackup_cleanup();
|
||||
+}
|
||||
+
|
||||
+void qmp_backup_cancel(Error **errp)
|
||||
+{
|
||||
+ Coroutine *co = qemu_coroutine_create(pvebackup_cancel, NULL);
|
||||
+ qemu_coroutine_enter(co);
|
||||
+
|
||||
+ while (backup_state.vmaw) {
|
||||
+ /* vma writer use main aio context */
|
||||
+ aio_poll(qemu_get_aio_context(), true);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+bool block_job_should_pause(BlockJob *job);
|
||||
+static void pvebackup_run_next_job(void)
|
||||
+{
|
||||
+ GList *l = backup_state.di_list;
|
||||
+ while (l) {
|
||||
+ PVEBackupDevInfo *di = (PVEBackupDevInfo *)l->data;
|
||||
+ l = g_list_next(l);
|
||||
+ if (!di->completed && di->bs && di->bs->job) {
|
||||
+ BlockJob *job = di->bs->job;
|
||||
+ if (block_job_should_pause(job)) {
|
||||
+ bool cancel = backup_state.error || backup_state.cancel;
|
||||
+ if (cancel) {
|
||||
+ block_job_cancel(job);
|
||||
+ } else {
|
||||
+ block_job_resume(job);
|
||||
+ }
|
||||
+ }
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ pvebackup_cleanup();
|
||||
+}
|
||||
+
|
||||
+UuidInfo *qmp_backup(const char *backup_file, bool has_format,
|
||||
+ BackupFormat format,
|
||||
+ bool has_config_file, const char *config_file,
|
||||
+ bool has_devlist, const char *devlist,
|
||||
+ bool has_speed, int64_t speed, Error **errp)
|
||||
+{
|
||||
+ BlockBackend *blk;
|
||||
+ BlockDriverState *bs = NULL;
|
||||
+ Error *local_err = NULL;
|
||||
+ uuid_t uuid;
|
||||
+ VmaWriter *vmaw = NULL;
|
||||
+ gchar **devs = NULL;
|
||||
+ GList *di_list = NULL;
|
||||
+ GList *l;
|
||||
+ UuidInfo *uuid_info;
|
||||
+
|
||||
+ if (backup_state.di_list) {
|
||||
+ error_set(errp, ERROR_CLASS_GENERIC_ERROR,
|
||||
+ "previous backup not finished");
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ /* Todo: try to auto-detect format based on file name */
|
||||
+ format = has_format ? format : BACKUP_FORMAT_VMA;
|
||||
+
|
||||
+ if (format != BACKUP_FORMAT_VMA) {
|
||||
+ error_set(errp, ERROR_CLASS_GENERIC_ERROR, "unknown backup format");
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ if (has_devlist) {
|
||||
+ devs = g_strsplit_set(devlist, ",;:", -1);
|
||||
+
|
||||
+ gchar **d = devs;
|
||||
+ while (d && *d) {
|
||||
+ blk = blk_by_name(*d);
|
||||
+ if (blk) {
|
||||
+ bs = blk_bs(blk);
|
||||
+ if (bdrv_is_read_only(bs)) {
|
||||
+ error_setg(errp, "Node '%s' is read only", *d);
|
||||
+ goto err;
|
||||
+ }
|
||||
+ if (!bdrv_is_inserted(bs)) {
|
||||
+ error_setg(errp, QERR_DEVICE_HAS_NO_MEDIUM, *d);
|
||||
+ goto err;
|
||||
+ }
|
||||
+ PVEBackupDevInfo *di = g_new0(PVEBackupDevInfo, 1);
|
||||
+ di->bs = bs;
|
||||
+ di_list = g_list_append(di_list, di);
|
||||
+ } else {
|
||||
+ error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
|
||||
+ "Device '%s' not found", *d);
|
||||
+ goto err;
|
||||
+ }
|
||||
+ d++;
|
||||
+ }
|
||||
+
|
||||
+ } else {
|
||||
+ BdrvNextIterator it;
|
||||
+
|
||||
+ bs = NULL;
|
||||
+ for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) {
|
||||
+ if (!bdrv_is_inserted(bs) || bdrv_is_read_only(bs)) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ PVEBackupDevInfo *di = g_new0(PVEBackupDevInfo, 1);
|
||||
+ di->bs = bs;
|
||||
+ di_list = g_list_append(di_list, di);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (!di_list) {
|
||||
+ error_set(errp, ERROR_CLASS_GENERIC_ERROR, "empty device list");
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ size_t total = 0;
|
||||
+
|
||||
+ l = di_list;
|
||||
+ while (l) {
|
||||
+ PVEBackupDevInfo *di = (PVEBackupDevInfo *)l->data;
|
||||
+ l = g_list_next(l);
|
||||
+ if (bdrv_op_is_blocked(di->bs, BLOCK_OP_TYPE_BACKUP_SOURCE, errp)) {
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ ssize_t size = bdrv_getlength(di->bs);
|
||||
+ if (size < 0) {
|
||||
+ error_setg_errno(errp, -di->size, "bdrv_getlength failed");
|
||||
+ goto err;
|
||||
+ }
|
||||
+ di->size = size;
|
||||
+ total += size;
|
||||
+ }
|
||||
+
|
||||
+ uuid_generate(uuid);
|
||||
+
|
||||
+ vmaw = vma_writer_create(backup_file, uuid, &local_err);
|
||||
+ if (!vmaw) {
|
||||
+ if (local_err) {
|
||||
+ error_propagate(errp, local_err);
|
||||
+ }
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ /* register all devices for vma writer */
|
||||
+ l = di_list;
|
||||
+ while (l) {
|
||||
+ PVEBackupDevInfo *di = (PVEBackupDevInfo *)l->data;
|
||||
+ l = g_list_next(l);
|
||||
+
|
||||
+ const char *devname = bdrv_get_device_name(di->bs);
|
||||
+ di->dev_id = vma_writer_register_stream(vmaw, devname, di->size);
|
||||
+ if (di->dev_id <= 0) {
|
||||
+ error_set(errp, ERROR_CLASS_GENERIC_ERROR,
|
||||
+ "register_stream failed");
|
||||
+ goto err;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* add configuration file to archive */
|
||||
+ if (has_config_file) {
|
||||
+ char *cdata = NULL;
|
||||
+ gsize clen = 0;
|
||||
+ GError *err = NULL;
|
||||
+ if (!g_file_get_contents(config_file, &cdata, &clen, &err)) {
|
||||
+ error_setg(errp, "unable to read file '%s'", config_file);
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ const char *basename = g_path_get_basename(config_file);
|
||||
+ if (vma_writer_add_config(vmaw, basename, cdata, clen) != 0) {
|
||||
+ error_setg(errp, "unable to add config data to vma archive");
|
||||
+ g_free(cdata);
|
||||
+ goto err;
|
||||
+ }
|
||||
+ g_free(cdata);
|
||||
+ }
|
||||
+
|
||||
+ /* initialize global backup_state now */
|
||||
+
|
||||
+ backup_state.cancel = false;
|
||||
+
|
||||
+ if (backup_state.error) {
|
||||
+ error_free(backup_state.error);
|
||||
+ backup_state.error = NULL;
|
||||
+ }
|
||||
+
|
||||
+ backup_state.speed = (has_speed && speed > 0) ? speed : 0;
|
||||
+
|
||||
+ backup_state.start_time = time(NULL);
|
||||
+ backup_state.end_time = 0;
|
||||
+
|
||||
+ if (backup_state.backup_file) {
|
||||
+ g_free(backup_state.backup_file);
|
||||
+ }
|
||||
+ backup_state.backup_file = g_strdup(backup_file);
|
||||
+
|
||||
+ backup_state.vmaw = vmaw;
|
||||
+
|
||||
+ uuid_copy(backup_state.uuid, uuid);
|
||||
+ uuid_unparse_lower(uuid, backup_state.uuid_str);
|
||||
+
|
||||
+ backup_state.di_list = di_list;
|
||||
+
|
||||
+ backup_state.total = total;
|
||||
+ backup_state.transferred = 0;
|
||||
+ backup_state.zero_bytes = 0;
|
||||
+
|
||||
+ /* start all jobs (paused state) */
|
||||
+ l = di_list;
|
||||
+ while (l) {
|
||||
+ PVEBackupDevInfo *di = (PVEBackupDevInfo *)l->data;
|
||||
+ l = g_list_next(l);
|
||||
+
|
||||
+ backup_job_create(NULL, di->bs, NULL, speed, MIRROR_SYNC_MODE_FULL, NULL,
|
||||
+ BLOCKDEV_ON_ERROR_REPORT, BLOCKDEV_ON_ERROR_REPORT,
|
||||
+ pvebackup_dump_cb, pvebackup_complete_cb, di,
|
||||
+ 1, NULL, &local_err);
|
||||
+ if (local_err != NULL) {
|
||||
+ error_setg(&backup_state.error, "backup_job_create failed");
|
||||
+ pvebackup_cancel(NULL);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (!backup_state.error) {
|
||||
+ pvebackup_run_next_job(); // run one job
|
||||
+ }
|
||||
+
|
||||
+ uuid_info = g_malloc0(sizeof(*uuid_info));
|
||||
+ uuid_info->UUID = g_strdup(backup_state.uuid_str);
|
||||
+ return uuid_info;
|
||||
+
|
||||
+err:
|
||||
+
|
||||
+ l = di_list;
|
||||
+ while (l) {
|
||||
+ g_free(l->data);
|
||||
+ l = g_list_next(l);
|
||||
+ }
|
||||
+ g_list_free(di_list);
|
||||
+
|
||||
+ if (devs) {
|
||||
+ g_strfreev(devs);
|
||||
+ }
|
||||
+
|
||||
+ if (vmaw) {
|
||||
+ Error *err = NULL;
|
||||
+ vma_writer_close(vmaw, &err);
|
||||
+ unlink(backup_file);
|
||||
+ }
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+BackupStatus *qmp_query_backup(Error **errp)
|
||||
+{
|
||||
+ BackupStatus *info = g_malloc0(sizeof(*info));
|
||||
+
|
||||
+ if (!backup_state.start_time) {
|
||||
+ /* not started, return {} */
|
||||
+ return info;
|
||||
+ }
|
||||
+
|
||||
+ info->has_status = true;
|
||||
+ info->has_start_time = true;
|
||||
+ info->start_time = backup_state.start_time;
|
||||
+
|
||||
+ if (backup_state.backup_file) {
|
||||
+ info->has_backup_file = true;
|
||||
+ info->backup_file = g_strdup(backup_state.backup_file);
|
||||
+ }
|
||||
+
|
||||
+ info->has_uuid = true;
|
||||
+ info->uuid = g_strdup(backup_state.uuid_str);
|
||||
+
|
||||
+ if (backup_state.end_time) {
|
||||
+ if (backup_state.error) {
|
||||
+ info->status = g_strdup("error");
|
||||
+ info->has_errmsg = true;
|
||||
+ info->errmsg = g_strdup(error_get_pretty(backup_state.error));
|
||||
+ } else {
|
||||
+ info->status = g_strdup("done");
|
||||
+ }
|
||||
+ info->has_end_time = true;
|
||||
+ info->end_time = backup_state.end_time;
|
||||
+ } else {
|
||||
+ info->status = g_strdup("active");
|
||||
+ }
|
||||
+
|
||||
+ info->has_total = true;
|
||||
+ info->total = backup_state.total;
|
||||
+ info->has_zero_bytes = true;
|
||||
+ info->zero_bytes = backup_state.zero_bytes;
|
||||
+ info->has_transferred = true;
|
||||
+ info->transferred = backup_state.transferred;
|
||||
+
|
||||
+ return info;
|
||||
+}
|
||||
+
|
||||
void qmp_block_stream(bool has_job_id, const char *job_id, const char *device,
|
||||
bool has_base, const char *base,
|
||||
bool has_base_node, const char *base_node,
|
||||
diff --git a/blockjob.c b/blockjob.c
|
||||
index 6e489327ff..2162b4d3d8 100644
|
||||
--- a/blockjob.c
|
||||
+++ b/blockjob.c
|
||||
@@ -37,8 +37,8 @@
|
||||
#include "qemu/timer.h"
|
||||
#include "qapi-event.h"
|
||||
|
||||
-static void block_job_event_cancelled(BlockJob *job);
|
||||
-static void block_job_event_completed(BlockJob *job, const char *msg);
|
||||
+void block_job_event_cancelled(BlockJob *job);
|
||||
+void block_job_event_completed(BlockJob *job, const char *msg);
|
||||
|
||||
/* Transactional group of block jobs */
|
||||
struct BlockJobTxn {
|
||||
@@ -473,7 +473,8 @@ void block_job_user_pause(BlockJob *job)
|
||||
block_job_pause(job);
|
||||
}
|
||||
|
||||
-static bool block_job_should_pause(BlockJob *job)
|
||||
+bool block_job_should_pause(BlockJob *job);
|
||||
+bool block_job_should_pause(BlockJob *job)
|
||||
{
|
||||
return job->pause_count > 0;
|
||||
}
|
||||
@@ -687,7 +688,7 @@ static void block_job_iostatus_set_err(BlockJob *job, int error)
|
||||
}
|
||||
}
|
||||
|
||||
-static void block_job_event_cancelled(BlockJob *job)
|
||||
+void block_job_event_cancelled(BlockJob *job)
|
||||
{
|
||||
if (block_job_is_internal(job)) {
|
||||
return;
|
||||
@@ -701,7 +702,7 @@ static void block_job_event_cancelled(BlockJob *job)
|
||||
&error_abort);
|
||||
}
|
||||
|
||||
-static void block_job_event_completed(BlockJob *job, const char *msg)
|
||||
+void block_job_event_completed(BlockJob *job, const char *msg)
|
||||
{
|
||||
if (block_job_is_internal(job)) {
|
||||
return;
|
||||
diff --git a/hmp-commands-info.hx b/hmp-commands-info.hx
|
||||
index a53f105c52..1a1838099f 100644
|
||||
--- a/hmp-commands-info.hx
|
||||
+++ b/hmp-commands-info.hx
|
||||
@@ -487,6 +487,19 @@ STEXI
|
||||
Show CPU statistics.
|
||||
ETEXI
|
||||
|
||||
+ {
|
||||
+ .name = "backup",
|
||||
+ .args_type = "",
|
||||
+ .params = "",
|
||||
+ .help = "show backup status",
|
||||
+ .cmd = hmp_info_backup,
|
||||
+ },
|
||||
+
|
||||
+STEXI
|
||||
+@item info backup
|
||||
+show backup status
|
||||
+ETEXI
|
||||
+
|
||||
#if defined(CONFIG_SLIRP)
|
||||
{
|
||||
.name = "usernet",
|
||||
diff --git a/hmp-commands.hx b/hmp-commands.hx
|
||||
index 88192817b2..aea39d0f45 100644
|
||||
--- a/hmp-commands.hx
|
||||
+++ b/hmp-commands.hx
|
||||
@@ -87,6 +87,35 @@ STEXI
|
||||
Copy data from a backing file into a block device.
|
||||
ETEXI
|
||||
|
||||
+ {
|
||||
+ .name = "backup",
|
||||
+ .args_type = "backupfile:s,speed:o?,devlist:s?",
|
||||
+ .params = "backupfile [speed [devlist]]",
|
||||
+ .help = "create a VM Backup.",
|
||||
+ .cmd = hmp_backup,
|
||||
+ },
|
||||
+
|
||||
+STEXI
|
||||
+@item backup
|
||||
+@findex backup
|
||||
+Create a VM backup.
|
||||
+ETEXI
|
||||
+
|
||||
+ {
|
||||
+ .name = "backup_cancel",
|
||||
+ .args_type = "",
|
||||
+ .params = "",
|
||||
+ .help = "cancel the current VM backup",
|
||||
+ .cmd = hmp_backup_cancel,
|
||||
+ },
|
||||
+
|
||||
+STEXI
|
||||
+@item backup_cancel
|
||||
+@findex backup_cancel
|
||||
+Cancel the current VM backup.
|
||||
+
|
||||
+ETEXI
|
||||
+
|
||||
{
|
||||
.name = "block_job_set_speed",
|
||||
.args_type = "device:B,speed:o",
|
||||
diff --git a/hmp.c b/hmp.c
|
||||
index 904542d026..c685ba507f 100644
|
||||
--- a/hmp.c
|
||||
+++ b/hmp.c
|
||||
@@ -151,6 +151,44 @@ void hmp_info_mice(Monitor *mon, const QDict *qdict)
|
||||
qapi_free_MouseInfoList(mice_list);
|
||||
}
|
||||
|
||||
+void hmp_info_backup(Monitor *mon, const QDict *qdict)
|
||||
+{
|
||||
+ BackupStatus *info;
|
||||
+
|
||||
+ info = qmp_query_backup(NULL);
|
||||
+ if (info->has_status) {
|
||||
+ if (info->has_errmsg) {
|
||||
+ monitor_printf(mon, "Backup status: %s - %s\n",
|
||||
+ info->status, info->errmsg);
|
||||
+ } else {
|
||||
+ monitor_printf(mon, "Backup status: %s\n", info->status);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (info->has_backup_file) {
|
||||
+ monitor_printf(mon, "Start time: %s", ctime(&info->start_time));
|
||||
+ if (info->end_time) {
|
||||
+ monitor_printf(mon, "End time: %s", ctime(&info->end_time));
|
||||
+ }
|
||||
+
|
||||
+ int per = (info->has_total && info->total &&
|
||||
+ info->has_transferred && info->transferred) ?
|
||||
+ (info->transferred * 100)/info->total : 0;
|
||||
+ int zero_per = (info->has_total && info->total &&
|
||||
+ info->has_zero_bytes && info->zero_bytes) ?
|
||||
+ (info->zero_bytes * 100)/info->total : 0;
|
||||
+ monitor_printf(mon, "Backup file: %s\n", info->backup_file);
|
||||
+ monitor_printf(mon, "Backup uuid: %s\n", info->uuid);
|
||||
+ monitor_printf(mon, "Total size: %zd\n", info->total);
|
||||
+ monitor_printf(mon, "Transferred bytes: %zd (%d%%)\n",
|
||||
+ info->transferred, per);
|
||||
+ monitor_printf(mon, "Zero bytes: %zd (%d%%)\n",
|
||||
+ info->zero_bytes, zero_per);
|
||||
+ }
|
||||
+
|
||||
+ qapi_free_BackupStatus(info);
|
||||
+}
|
||||
+
|
||||
void hmp_info_migrate(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
MigrationInfo *info;
|
||||
@@ -1613,6 +1651,29 @@ void hmp_block_stream(Monitor *mon, const QDict *qdict)
|
||||
hmp_handle_error(mon, &error);
|
||||
}
|
||||
|
||||
+void hmp_backup_cancel(Monitor *mon, const QDict *qdict)
|
||||
+{
|
||||
+ Error *error = NULL;
|
||||
+
|
||||
+ qmp_backup_cancel(&error);
|
||||
+
|
||||
+ hmp_handle_error(mon, &error);
|
||||
+}
|
||||
+
|
||||
+void hmp_backup(Monitor *mon, const QDict *qdict)
|
||||
+{
|
||||
+ Error *error = NULL;
|
||||
+
|
||||
+ const char *backup_file = qdict_get_str(qdict, "backupfile");
|
||||
+ const char *devlist = qdict_get_try_str(qdict, "devlist");
|
||||
+ int64_t speed = qdict_get_try_int(qdict, "speed", 0);
|
||||
+
|
||||
+ qmp_backup(backup_file, true, BACKUP_FORMAT_VMA, false, NULL, !!devlist,
|
||||
+ devlist, qdict_haskey(qdict, "speed"), speed, &error);
|
||||
+
|
||||
+ hmp_handle_error(mon, &error);
|
||||
+}
|
||||
+
|
||||
void hmp_block_job_set_speed(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
Error *error = NULL;
|
||||
diff --git a/hmp.h b/hmp.h
|
||||
index 799fd371fa..17a65b2313 100644
|
||||
--- a/hmp.h
|
||||
+++ b/hmp.h
|
||||
@@ -30,6 +30,7 @@ void hmp_info_migrate(Monitor *mon, const QDict *qdict);
|
||||
void hmp_info_migrate_capabilities(Monitor *mon, const QDict *qdict);
|
||||
void hmp_info_migrate_parameters(Monitor *mon, const QDict *qdict);
|
||||
void hmp_info_migrate_cache_size(Monitor *mon, const QDict *qdict);
|
||||
+void hmp_info_backup(Monitor *mon, const QDict *qdict);
|
||||
void hmp_info_cpus(Monitor *mon, const QDict *qdict);
|
||||
void hmp_info_block(Monitor *mon, const QDict *qdict);
|
||||
void hmp_info_blockstats(Monitor *mon, const QDict *qdict);
|
||||
@@ -79,6 +80,8 @@ void hmp_eject(Monitor *mon, const QDict *qdict);
|
||||
void hmp_change(Monitor *mon, const QDict *qdict);
|
||||
void hmp_block_set_io_throttle(Monitor *mon, const QDict *qdict);
|
||||
void hmp_block_stream(Monitor *mon, const QDict *qdict);
|
||||
+void hmp_backup(Monitor *mon, const QDict *qdict);
|
||||
+void hmp_backup_cancel(Monitor *mon, const QDict *qdict);
|
||||
void hmp_block_job_set_speed(Monitor *mon, const QDict *qdict);
|
||||
void hmp_block_job_cancel(Monitor *mon, const QDict *qdict);
|
||||
void hmp_block_job_pause(Monitor *mon, const QDict *qdict);
|
||||
diff --git a/include/block/block_int.h b/include/block/block_int.h
|
||||
index ec655815ca..278da161fb 100644
|
||||
--- a/include/block/block_int.h
|
||||
+++ b/include/block/block_int.h
|
||||
@@ -59,7 +59,7 @@
|
||||
|
||||
#define BLOCK_PROBE_BUF_SIZE 512
|
||||
|
||||
-typedef int BackupDumpFunc(void *opaque, BlockDriverState *bs,
|
||||
+typedef int BackupDumpFunc(void *opaque, BlockBackend *be,
|
||||
int64_t sector_num, int n_sectors, unsigned char *buf);
|
||||
|
||||
enum BdrvTrackedRequestType {
|
||||
diff --git a/qapi-schema.json b/qapi-schema.json
|
||||
index 1b14ff2476..12d4d20705 100644
|
||||
--- a/qapi-schema.json
|
||||
+++ b/qapi-schema.json
|
||||
@@ -570,6 +570,96 @@
|
||||
{ 'command': 'query-events', 'returns': ['EventInfo'] }
|
||||
|
||||
##
|
||||
+# @BackupStatus:
|
||||
+#
|
||||
+# Detailed backup status.
|
||||
+#
|
||||
+# @status: string describing the current backup status.
|
||||
+# This can be 'active', 'done', 'error'. If this field is not
|
||||
+# returned, no backup process has been initiated
|
||||
+#
|
||||
+# @errmsg: error message (only returned if status is 'error')
|
||||
+#
|
||||
+# @total: total amount of bytes involved in the backup process
|
||||
+#
|
||||
+# @transferred: amount of bytes already backed up.
|
||||
+#
|
||||
+# @zero-bytes: amount of 'zero' bytes detected.
|
||||
+#
|
||||
+# @start-time: time (epoch) when backup job started.
|
||||
+#
|
||||
+# @end-time: time (epoch) when backup job finished.
|
||||
+#
|
||||
+# @backup-file: backup file name
|
||||
+#
|
||||
+# @uuid: uuid for this backup job
|
||||
+#
|
||||
+##
|
||||
+{ 'struct': 'BackupStatus',
|
||||
+ 'data': {'*status': 'str', '*errmsg': 'str', '*total': 'int',
|
||||
+ '*transferred': 'int', '*zero-bytes': 'int',
|
||||
+ '*start-time': 'int', '*end-time': 'int',
|
||||
+ '*backup-file': 'str', '*uuid': 'str' } }
|
||||
+
|
||||
+##
|
||||
+# @BackupFormat:
|
||||
+#
|
||||
+# An enumeration of supported backup formats.
|
||||
+#
|
||||
+# @vma: Proxmox vma backup format
|
||||
+##
|
||||
+{ 'enum': 'BackupFormat',
|
||||
+ 'data': [ 'vma' ] }
|
||||
+
|
||||
+##
|
||||
+# @backup:
|
||||
+#
|
||||
+# Starts a VM backup.
|
||||
+#
|
||||
+# @backup-file: the backup file name
|
||||
+#
|
||||
+# @format: format of the backup file
|
||||
+#
|
||||
+# @config-file: a configuration file to include into
|
||||
+# the backup archive.
|
||||
+#
|
||||
+# @speed: the maximum speed, in bytes per second
|
||||
+#
|
||||
+# @devlist: list of block device names (separated by ',', ';'
|
||||
+# or ':'). By default the backup includes all writable block devices.
|
||||
+#
|
||||
+# Returns: the uuid of the backup job
|
||||
+#
|
||||
+##
|
||||
+{ 'command': 'backup', 'data': { 'backup-file': 'str',
|
||||
+ '*format': 'BackupFormat',
|
||||
+ '*config-file': 'str',
|
||||
+ '*devlist': 'str', '*speed': 'int' },
|
||||
+ 'returns': 'UuidInfo' }
|
||||
+
|
||||
+##
|
||||
+# @query-backup:
|
||||
+#
|
||||
+# Returns information about current/last backup task.
|
||||
+#
|
||||
+# Returns: @BackupStatus
|
||||
+#
|
||||
+##
|
||||
+{ 'command': 'query-backup', 'returns': 'BackupStatus' }
|
||||
+
|
||||
+##
|
||||
+# @backup-cancel:
|
||||
+#
|
||||
+# Cancel the current executing backup process.
|
||||
+#
|
||||
+# Returns: nothing on success
|
||||
+#
|
||||
+# Notes: This command succeeds even if there is no backup process running.
|
||||
+#
|
||||
+##
|
||||
+{ 'command': 'backup-cancel' }
|
||||
+
|
||||
+##
|
||||
# @MigrationStats:
|
||||
#
|
||||
# Detailed migration status.
|
||||
--
|
||||
2.11.0
|
||||
|
@ -1,7 +1,7 @@
|
||||
From 6c2823a8f34f9edd061a8c56af8fa0fb5014c507 Mon Sep 17 00:00:00 2001
|
||||
From 8c4c8041d0cb8523af453e1d1a8408215db6964f Mon Sep 17 00:00:00 2001
|
||||
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
|
||||
Date: Wed, 9 Dec 2015 14:17:38 +0100
|
||||
Subject: [PATCH 03/49] vnc: altgr emulation
|
||||
Subject: [PATCH 15/28] vnc: altgr emulation
|
||||
|
||||
---
|
||||
ui/vnc.c | 26 +++++++++++++++++++++++++-
|
@ -1,315 +0,0 @@
|
||||
From 1fc4d337a3935f0e80a78f8b14bdda839257ded9 Mon Sep 17 00:00:00 2001
|
||||
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
|
||||
Date: Wed, 9 Dec 2015 15:21:54 +0100
|
||||
Subject: [PATCH 16/49] backup: vma: add dir format
|
||||
|
||||
---
|
||||
blockdev.c | 137 ++++++++++++++++++++++++++++++++++++++++---------------
|
||||
hmp-commands.hx | 8 ++--
|
||||
hmp.c | 4 +-
|
||||
qapi-schema.json | 2 +-
|
||||
vma.c | 2 +-
|
||||
5 files changed, 111 insertions(+), 42 deletions(-)
|
||||
|
||||
diff --git a/blockdev.c b/blockdev.c
|
||||
index 58cf5d3c80..87e1d1a99e 100644
|
||||
--- a/blockdev.c
|
||||
+++ b/blockdev.c
|
||||
@@ -3007,6 +3007,8 @@ typedef struct PVEBackupDevInfo {
|
||||
uint8_t dev_id;
|
||||
//bool started;
|
||||
bool completed;
|
||||
+ char targetfile[PATH_MAX];
|
||||
+ BlockDriverState *target;
|
||||
} PVEBackupDevInfo;
|
||||
|
||||
static void pvebackup_run_next_job(void);
|
||||
@@ -3075,8 +3077,6 @@ static void pvebackup_complete_cb(void *opaque, int ret)
|
||||
{
|
||||
PVEBackupDevInfo *di = opaque;
|
||||
|
||||
- assert(backup_state.vmaw);
|
||||
-
|
||||
di->completed = true;
|
||||
|
||||
if (ret < 0 && !backup_state.error) {
|
||||
@@ -3087,8 +3087,11 @@ static void pvebackup_complete_cb(void *opaque, int ret)
|
||||
BlockDriverState *bs = di->bs;
|
||||
|
||||
di->bs = NULL;
|
||||
+ di->target = NULL;
|
||||
|
||||
- vma_writer_close_stream(backup_state.vmaw, di->dev_id);
|
||||
+ if (backup_state.vmaw) {
|
||||
+ vma_writer_close_stream(backup_state.vmaw, di->dev_id);
|
||||
+ }
|
||||
|
||||
block_job_cb(bs, ret);
|
||||
|
||||
@@ -3168,6 +3171,7 @@ UuidInfo *qmp_backup(const char *backup_file, bool has_format,
|
||||
{
|
||||
BlockBackend *blk;
|
||||
BlockDriverState *bs = NULL;
|
||||
+ const char *backup_dir = NULL;
|
||||
Error *local_err = NULL;
|
||||
uuid_t uuid;
|
||||
VmaWriter *vmaw = NULL;
|
||||
@@ -3175,6 +3179,7 @@ UuidInfo *qmp_backup(const char *backup_file, bool has_format,
|
||||
GList *di_list = NULL;
|
||||
GList *l;
|
||||
UuidInfo *uuid_info;
|
||||
+ BlockJob *job;
|
||||
|
||||
if (backup_state.di_list) {
|
||||
error_set(errp, ERROR_CLASS_GENERIC_ERROR,
|
||||
@@ -3185,11 +3190,6 @@ UuidInfo *qmp_backup(const char *backup_file, bool has_format,
|
||||
/* Todo: try to auto-detect format based on file name */
|
||||
format = has_format ? format : BACKUP_FORMAT_VMA;
|
||||
|
||||
- if (format != BACKUP_FORMAT_VMA) {
|
||||
- error_set(errp, ERROR_CLASS_GENERIC_ERROR, "unknown backup format");
|
||||
- return NULL;
|
||||
- }
|
||||
-
|
||||
if (has_devlist) {
|
||||
devs = g_strsplit_set(devlist, ",;:", -1);
|
||||
|
||||
@@ -3258,27 +3258,62 @@ UuidInfo *qmp_backup(const char *backup_file, bool has_format,
|
||||
|
||||
uuid_generate(uuid);
|
||||
|
||||
- vmaw = vma_writer_create(backup_file, uuid, &local_err);
|
||||
- if (!vmaw) {
|
||||
- if (local_err) {
|
||||
- error_propagate(errp, local_err);
|
||||
+ if (format == BACKUP_FORMAT_VMA) {
|
||||
+ vmaw = vma_writer_create(backup_file, uuid, &local_err);
|
||||
+ if (!vmaw) {
|
||||
+ if (local_err) {
|
||||
+ error_propagate(errp, local_err);
|
||||
+ }
|
||||
+ goto err;
|
||||
}
|
||||
- goto err;
|
||||
- }
|
||||
|
||||
- /* register all devices for vma writer */
|
||||
- l = di_list;
|
||||
- while (l) {
|
||||
- PVEBackupDevInfo *di = (PVEBackupDevInfo *)l->data;
|
||||
- l = g_list_next(l);
|
||||
+ /* register all devices for vma writer */
|
||||
+ l = di_list;
|
||||
+ while (l) {
|
||||
+ PVEBackupDevInfo *di = (PVEBackupDevInfo *)l->data;
|
||||
+ l = g_list_next(l);
|
||||
|
||||
- const char *devname = bdrv_get_device_name(di->bs);
|
||||
- di->dev_id = vma_writer_register_stream(vmaw, devname, di->size);
|
||||
- if (di->dev_id <= 0) {
|
||||
- error_set(errp, ERROR_CLASS_GENERIC_ERROR,
|
||||
- "register_stream failed");
|
||||
+ const char *devname = bdrv_get_device_name(di->bs);
|
||||
+ di->dev_id = vma_writer_register_stream(vmaw, devname, di->size);
|
||||
+ if (di->dev_id <= 0) {
|
||||
+ error_set(errp, ERROR_CLASS_GENERIC_ERROR,
|
||||
+ "register_stream failed");
|
||||
+ goto err;
|
||||
+ }
|
||||
+ }
|
||||
+ } else if (format == BACKUP_FORMAT_DIR) {
|
||||
+ if (mkdir(backup_file, 0640) != 0) {
|
||||
+ error_setg_errno(errp, errno, "can't create directory '%s'\n",
|
||||
+ backup_file);
|
||||
goto err;
|
||||
}
|
||||
+ backup_dir = backup_file;
|
||||
+
|
||||
+ l = di_list;
|
||||
+ while (l) {
|
||||
+ PVEBackupDevInfo *di = (PVEBackupDevInfo *)l->data;
|
||||
+ l = g_list_next(l);
|
||||
+
|
||||
+ const char *devname = bdrv_get_device_name(di->bs);
|
||||
+ snprintf(di->targetfile, PATH_MAX, "%s/%s.raw", backup_dir, devname);
|
||||
+
|
||||
+ int flags = BDRV_O_RDWR;
|
||||
+ bdrv_img_create(di->targetfile, "raw", NULL, NULL, NULL,
|
||||
+ di->size, flags, &local_err, false);
|
||||
+ if (local_err) {
|
||||
+ error_propagate(errp, local_err);
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ di->target = bdrv_open(di->targetfile, NULL, NULL, flags, &local_err);
|
||||
+ if (!di->target) {
|
||||
+ error_propagate(errp, local_err);
|
||||
+ goto err;
|
||||
+ }
|
||||
+ }
|
||||
+ } else {
|
||||
+ error_set(errp, ERROR_CLASS_GENERIC_ERROR, "unknown backup format");
|
||||
+ goto err;
|
||||
}
|
||||
|
||||
/* add configuration file to archive */
|
||||
@@ -3291,12 +3326,27 @@ UuidInfo *qmp_backup(const char *backup_file, bool has_format,
|
||||
goto err;
|
||||
}
|
||||
|
||||
- const char *basename = g_path_get_basename(config_file);
|
||||
- if (vma_writer_add_config(vmaw, basename, cdata, clen) != 0) {
|
||||
- error_setg(errp, "unable to add config data to vma archive");
|
||||
- g_free(cdata);
|
||||
- goto err;
|
||||
+ char *basename = g_path_get_basename(config_file);
|
||||
+
|
||||
+ if (format == BACKUP_FORMAT_VMA) {
|
||||
+ if (vma_writer_add_config(vmaw, basename, cdata, clen) != 0) {
|
||||
+ error_setg(errp, "unable to add config data to vma archive");
|
||||
+ g_free(cdata);
|
||||
+ g_free(basename);
|
||||
+ goto err;
|
||||
+ }
|
||||
+ } else if (format == BACKUP_FORMAT_DIR) {
|
||||
+ char config_path[PATH_MAX];
|
||||
+ snprintf(config_path, PATH_MAX, "%s/%s", backup_dir, basename);
|
||||
+ if (!g_file_set_contents(config_path, cdata, clen, &err)) {
|
||||
+ error_setg(errp, "unable to write config file '%s'", config_path);
|
||||
+ g_free(cdata);
|
||||
+ g_free(basename);
|
||||
+ goto err;
|
||||
+ }
|
||||
}
|
||||
+
|
||||
+ g_free(basename);
|
||||
g_free(cdata);
|
||||
}
|
||||
|
||||
@@ -3335,15 +3385,16 @@ UuidInfo *qmp_backup(const char *backup_file, bool has_format,
|
||||
while (l) {
|
||||
PVEBackupDevInfo *di = (PVEBackupDevInfo *)l->data;
|
||||
l = g_list_next(l);
|
||||
-
|
||||
- backup_job_create(NULL, di->bs, NULL, speed, MIRROR_SYNC_MODE_FULL, NULL,
|
||||
- BLOCKDEV_ON_ERROR_REPORT, BLOCKDEV_ON_ERROR_REPORT,
|
||||
- pvebackup_dump_cb, pvebackup_complete_cb, di,
|
||||
- 1, NULL, &local_err);
|
||||
- if (local_err != NULL) {
|
||||
+ job = backup_job_create(NULL, di->bs, di->target, speed, MIRROR_SYNC_MODE_FULL, NULL,
|
||||
+ false, BLOCKDEV_ON_ERROR_REPORT, BLOCKDEV_ON_ERROR_REPORT,
|
||||
+ BLOCK_JOB_DEFAULT,
|
||||
+ pvebackup_dump_cb, pvebackup_complete_cb, di,
|
||||
+ 1, NULL, &local_err);
|
||||
+ if (!job || local_err != NULL) {
|
||||
error_setg(&backup_state.error, "backup_job_create failed");
|
||||
pvebackup_cancel(NULL);
|
||||
}
|
||||
+ block_job_start(job);
|
||||
}
|
||||
|
||||
if (!backup_state.error) {
|
||||
@@ -3352,14 +3403,24 @@ UuidInfo *qmp_backup(const char *backup_file, bool has_format,
|
||||
|
||||
uuid_info = g_malloc0(sizeof(*uuid_info));
|
||||
uuid_info->UUID = g_strdup(backup_state.uuid_str);
|
||||
+
|
||||
return uuid_info;
|
||||
|
||||
err:
|
||||
|
||||
l = di_list;
|
||||
while (l) {
|
||||
- g_free(l->data);
|
||||
+ PVEBackupDevInfo *di = (PVEBackupDevInfo *)l->data;
|
||||
l = g_list_next(l);
|
||||
+
|
||||
+ if (di->target) {
|
||||
+ bdrv_unref(di->target);
|
||||
+ }
|
||||
+
|
||||
+ if (di->targetfile[0]) {
|
||||
+ unlink(di->targetfile);
|
||||
+ }
|
||||
+ g_free(di);
|
||||
}
|
||||
g_list_free(di_list);
|
||||
|
||||
@@ -3373,6 +3434,10 @@ err:
|
||||
unlink(backup_file);
|
||||
}
|
||||
|
||||
+ if (backup_dir) {
|
||||
+ rmdir(backup_dir);
|
||||
+ }
|
||||
+
|
||||
return NULL;
|
||||
}
|
||||
|
||||
diff --git a/hmp-commands.hx b/hmp-commands.hx
|
||||
index aea39d0f45..72882039ee 100644
|
||||
--- a/hmp-commands.hx
|
||||
+++ b/hmp-commands.hx
|
||||
@@ -89,9 +89,11 @@ ETEXI
|
||||
|
||||
{
|
||||
.name = "backup",
|
||||
- .args_type = "backupfile:s,speed:o?,devlist:s?",
|
||||
- .params = "backupfile [speed [devlist]]",
|
||||
- .help = "create a VM Backup.",
|
||||
+ .args_type = "directory:-d,backupfile:s,speed:o?,devlist:s?",
|
||||
+ .params = "[-d] backupfile [speed [devlist]]",
|
||||
+ .help = "create a VM Backup."
|
||||
+ "\n\t\t\t Use -d to dump data into a directory instead"
|
||||
+ "\n\t\t\t of using VMA format.",
|
||||
.cmd = hmp_backup,
|
||||
},
|
||||
|
||||
diff --git a/hmp.c b/hmp.c
|
||||
index c685ba507f..465d7faad0 100644
|
||||
--- a/hmp.c
|
||||
+++ b/hmp.c
|
||||
@@ -1664,11 +1664,13 @@ void hmp_backup(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
Error *error = NULL;
|
||||
|
||||
+ int dir = qdict_get_try_bool(qdict, "directory", 0);
|
||||
const char *backup_file = qdict_get_str(qdict, "backupfile");
|
||||
const char *devlist = qdict_get_try_str(qdict, "devlist");
|
||||
int64_t speed = qdict_get_try_int(qdict, "speed", 0);
|
||||
|
||||
- qmp_backup(backup_file, true, BACKUP_FORMAT_VMA, false, NULL, !!devlist,
|
||||
+ qmp_backup(backup_file, true, dir ? BACKUP_FORMAT_DIR : BACKUP_FORMAT_VMA,
|
||||
+ false, NULL, !!devlist,
|
||||
devlist, qdict_haskey(qdict, "speed"), speed, &error);
|
||||
|
||||
hmp_handle_error(mon, &error);
|
||||
diff --git a/qapi-schema.json b/qapi-schema.json
|
||||
index 12d4d20705..edb7c32ac9 100644
|
||||
--- a/qapi-schema.json
|
||||
+++ b/qapi-schema.json
|
||||
@@ -609,7 +609,7 @@
|
||||
# @vma: Proxmox vma backup format
|
||||
##
|
||||
{ 'enum': 'BackupFormat',
|
||||
- 'data': [ 'vma' ] }
|
||||
+ 'data': [ 'vma', 'dir' ] }
|
||||
|
||||
##
|
||||
# @backup:
|
||||
diff --git a/vma.c b/vma.c
|
||||
index 89254070c4..1ffaced897 100644
|
||||
--- a/vma.c
|
||||
+++ b/vma.c
|
||||
@@ -264,7 +264,7 @@ static int extract_content(int argc, char **argv)
|
||||
g_free(statefn);
|
||||
} else if (di) {
|
||||
char *devfn = NULL;
|
||||
- int flags = BDRV_O_RDWR|BDRV_O_CACHE_WB;
|
||||
+ int flags = BDRV_O_RDWR;
|
||||
bool write_zero = true;
|
||||
|
||||
if (readmap) {
|
||||
--
|
||||
2.11.0
|
||||
|
@ -1,7 +1,7 @@
|
||||
From d4cccacea777bdf4ce379a0d889acbfd05fcdf05 Mon Sep 17 00:00:00 2001
|
||||
From e90d84abb42bc2befe9a48a9be2873d5dce68236 Mon Sep 17 00:00:00 2001
|
||||
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
|
||||
Date: Tue, 12 Jan 2016 09:09:49 +0100
|
||||
Subject: [PATCH 29/49] vnc: make x509 imply tls again
|
||||
Subject: [PATCH 16/28] vnc: make x509 imply tls again
|
||||
|
||||
---
|
||||
ui/vnc.c | 5 ++---
|
@ -1,77 +0,0 @@
|
||||
From c8fdc50eaa27500204364f15de1aac2c0ac07bf8 Mon Sep 17 00:00:00 2001
|
||||
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
|
||||
Date: Wed, 9 Dec 2015 15:22:19 +0100
|
||||
Subject: [PATCH 17/49] backup: do not return errors in dump callback
|
||||
|
||||
---
|
||||
blockdev.c | 26 ++++++++++++++++++++------
|
||||
1 file changed, 20 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/blockdev.c b/blockdev.c
|
||||
index 87e1d1a99e..5017c276e6 100644
|
||||
--- a/blockdev.c
|
||||
+++ b/blockdev.c
|
||||
@@ -3019,6 +3019,11 @@ static int pvebackup_dump_cb(void *opaque, BlockBackend *target,
|
||||
{
|
||||
PVEBackupDevInfo *di = opaque;
|
||||
|
||||
+ int size = n_sectors * BDRV_SECTOR_SIZE;
|
||||
+ if (backup_state.cancel) {
|
||||
+ return size; // return success
|
||||
+ }
|
||||
+
|
||||
if (sector_num & 0x7f) {
|
||||
if (!backup_state.error) {
|
||||
error_setg(&backup_state.error,
|
||||
@@ -3029,7 +3034,6 @@ static int pvebackup_dump_cb(void *opaque, BlockBackend *target,
|
||||
}
|
||||
|
||||
int64_t cluster_num = sector_num >> 7;
|
||||
- int size = n_sectors * BDRV_SECTOR_SIZE;
|
||||
|
||||
int ret = -1;
|
||||
|
||||
@@ -3037,17 +3041,27 @@ static int pvebackup_dump_cb(void *opaque, BlockBackend *target,
|
||||
size_t zero_bytes = 0;
|
||||
ret = vma_writer_write(backup_state.vmaw, di->dev_id, cluster_num,
|
||||
buf, &zero_bytes);
|
||||
- backup_state.zero_bytes += zero_bytes;
|
||||
+ if (ret < 0) {
|
||||
+ if (!backup_state.error) {
|
||||
+ error_setg(&backup_state.error, "vma_writer_write error %d", ret);
|
||||
+ }
|
||||
+ if (di->bs && di->bs->job) {
|
||||
+ block_job_cancel(di->bs->job);
|
||||
+ }
|
||||
+ } else {
|
||||
+ backup_state.zero_bytes += zero_bytes;
|
||||
+ backup_state.transferred += size;
|
||||
+ }
|
||||
} else {
|
||||
- ret = size;
|
||||
if (!buf) {
|
||||
backup_state.zero_bytes += size;
|
||||
}
|
||||
+ backup_state.transferred += size;
|
||||
}
|
||||
|
||||
- backup_state.transferred += size;
|
||||
+ // Note: always return success, because we want that writes succeed anyways.
|
||||
|
||||
- return ret;
|
||||
+ return size;
|
||||
}
|
||||
|
||||
static void pvebackup_cleanup(void)
|
||||
@@ -3119,7 +3133,7 @@ static void pvebackup_cancel(void *opaque)
|
||||
BlockJob *job = di->bs->job;
|
||||
if (job) {
|
||||
if (!di->completed) {
|
||||
- block_job_cancel_sync(job);
|
||||
+ block_job_cancel_sync(job);
|
||||
}
|
||||
}
|
||||
}
|
||||
--
|
||||
2.11.0
|
||||
|
@ -1,7 +1,7 @@
|
||||
From 503d2744e7e5cfdca939404488ee2b3f43894425 Mon Sep 17 00:00:00 2001
|
||||
From e9712692a0a336bf56025e1bc8056636cbd3931e Mon Sep 17 00:00:00 2001
|
||||
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
|
||||
Date: Mon, 11 Jan 2016 10:40:31 +0100
|
||||
Subject: [PATCH 30/49] PVE VNC authentication
|
||||
Subject: [PATCH 17/28] vnc: PVE VNC authentication
|
||||
|
||||
---
|
||||
crypto/tlscreds.c | 47 +++++++++++
|
||||
@ -11,11 +11,11 @@ Subject: [PATCH 30/49] PVE VNC authentication
|
||||
include/crypto/tlscreds.h | 1 +
|
||||
include/ui/console.h | 1 +
|
||||
qemu-options.hx | 3 +
|
||||
ui/vnc-auth-vencrypt.c | 196 ++++++++++++++++++++++++++++++++++++++--------
|
||||
ui/vnc.c | 140 ++++++++++++++++++++++++++++++++-
|
||||
ui/vnc-auth-vencrypt.c | 197 ++++++++++++++++++++++++++++++++++++++--------
|
||||
ui/vnc.c | 140 +++++++++++++++++++++++++++++++-
|
||||
ui/vnc.h | 4 +
|
||||
vl.c | 9 +++
|
||||
11 files changed, 376 insertions(+), 41 deletions(-)
|
||||
11 files changed, 377 insertions(+), 41 deletions(-)
|
||||
|
||||
diff --git a/crypto/tlscreds.c b/crypto/tlscreds.c
|
||||
index a8965531b6..e9ae13ce47 100644
|
||||
@ -194,34 +194,30 @@ index 10f0e81f9b..fbd1a1cecf 100644
|
||||
"-fda/-fdb file use 'file' as floppy disk 0/1 image\n", QEMU_ARCH_ALL)
|
||||
DEF("fdb", HAS_ARG, QEMU_OPTION_fdb, "", QEMU_ARCH_ALL)
|
||||
diff --git a/ui/vnc-auth-vencrypt.c b/ui/vnc-auth-vencrypt.c
|
||||
index ffaab57550..de1c1949ba 100644
|
||||
index ffaab57550..594ca737a9 100644
|
||||
--- a/ui/vnc-auth-vencrypt.c
|
||||
+++ b/ui/vnc-auth-vencrypt.c
|
||||
@@ -28,6 +28,107 @@
|
||||
@@ -28,6 +28,108 @@
|
||||
#include "vnc.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qemu/main-loop.h"
|
||||
+#include "qemu/sockets.h"
|
||||
+#include "io/channel-socket.h"
|
||||
+
|
||||
+static int protocol_client_auth_plain(VncState *vs, uint8_t *data, size_t len)
|
||||
+{
|
||||
+ const char *err = NULL;
|
||||
+ Error *err = NULL;
|
||||
+ char username[256];
|
||||
+ char passwd[512];
|
||||
+
|
||||
+ char clientip[256];
|
||||
+ clientip[0] = 0;
|
||||
+ struct sockaddr_in client;
|
||||
+ socklen_t addrlen = sizeof(client);
|
||||
+ if (getpeername(vs->csock, &client, &addrlen) == 0) {
|
||||
+ inet_ntop(client.sin_family, &client.sin_addr,
|
||||
+ clientip, sizeof(clientip));
|
||||
+ SocketAddress *clientip = qio_channel_socket_get_remote_address(vs->sioc, &err);
|
||||
+ if (err) {
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ if ((len != (vs->username_len + vs->password_len)) ||
|
||||
+ (vs->username_len >= (sizeof(username)-1)) ||
|
||||
+ (vs->password_len >= (sizeof(passwd)-1)) ) {
|
||||
+ err = "Got unexpected data length";
|
||||
+ error_setg(&err, "Got unexpected data length");
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
@ -232,26 +228,31 @@ index ffaab57550..de1c1949ba 100644
|
||||
+
|
||||
+ VNC_DEBUG("AUTH PLAIN username: %s pw: %s\n", username, passwd);
|
||||
+
|
||||
+ if (pve_auth_verify(clientip, username, passwd) == 0) {
|
||||
+ if (pve_auth_verify(clientip->u.inet.data->host, username, passwd) == 0) {
|
||||
+ vnc_write_u32(vs, 0); /* Accept auth completion */
|
||||
+ start_client_init(vs);
|
||||
+ qapi_free_SocketAddress(clientip);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ err = "Authentication failed";
|
||||
+ error_setg(&err, "Authentication failed");
|
||||
+err:
|
||||
+ if (err) {
|
||||
+ VNC_DEBUG("AUTH PLAIN ERROR: %s\n", err);
|
||||
+ const char *err_msg = error_get_pretty(err);
|
||||
+ VNC_DEBUG("AUTH PLAIN ERROR: %s\n", err_msg);
|
||||
+ vnc_write_u32(vs, 1); /* Reject auth */
|
||||
+ if (vs->minor >= 8) {
|
||||
+ int elen = strlen(err);
|
||||
+ int elen = strlen(err_msg);
|
||||
+ vnc_write_u32(vs, elen);
|
||||
+ vnc_write(vs, err, elen);
|
||||
+ vnc_write(vs, err_msg, elen);
|
||||
+ }
|
||||
+ error_free(err);
|
||||
+ }
|
||||
+ vnc_flush(vs);
|
||||
+ vnc_client_error(vs);
|
||||
+
|
||||
+ qapi_free_SocketAddress(clientip);
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+}
|
||||
@ -305,7 +306,7 @@ index ffaab57550..de1c1949ba 100644
|
||||
|
||||
static void start_auth_vencrypt_subauth(VncState *vs)
|
||||
{
|
||||
@@ -39,6 +140,17 @@ static void start_auth_vencrypt_subauth(VncState *vs)
|
||||
@@ -39,6 +141,17 @@ static void start_auth_vencrypt_subauth(VncState *vs)
|
||||
start_client_init(vs);
|
||||
break;
|
||||
|
||||
@ -323,7 +324,7 @@ index ffaab57550..de1c1949ba 100644
|
||||
case VNC_AUTH_VENCRYPT_TLSVNC:
|
||||
case VNC_AUTH_VENCRYPT_X509VNC:
|
||||
VNC_DEBUG("Start TLS auth VNC\n");
|
||||
@@ -88,45 +200,64 @@ static int protocol_client_vencrypt_auth(VncState *vs, uint8_t *data, size_t len
|
||||
@@ -88,45 +201,64 @@ static int protocol_client_vencrypt_auth(VncState *vs, uint8_t *data, size_t len
|
||||
{
|
||||
int auth = read_u32(data, 0);
|
||||
|
||||
@ -418,7 +419,7 @@ index ffaab57550..de1c1949ba 100644
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -140,10 +271,11 @@ static int protocol_client_vencrypt_init(VncState *vs, uint8_t *data, size_t len
|
||||
@@ -140,10 +272,11 @@ static int protocol_client_vencrypt_init(VncState *vs, uint8_t *data, size_t len
|
||||
vnc_flush(vs);
|
||||
vnc_client_error(vs);
|
||||
} else {
|
@ -1,57 +0,0 @@
|
||||
From 95ae3ad5710a4128f27e53d4fd926aa8fe596459 Mon Sep 17 00:00:00 2001
|
||||
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
|
||||
Date: Wed, 9 Dec 2015 15:39:36 +0100
|
||||
Subject: [PATCH 18/49] backup: vma: correctly propagate error
|
||||
|
||||
---
|
||||
blockdev.c | 2 +-
|
||||
vma-writer.c | 7 +++++++
|
||||
vma.h | 1 +
|
||||
3 files changed, 9 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/blockdev.c b/blockdev.c
|
||||
index 5017c276e6..d3aef2cc83 100644
|
||||
--- a/blockdev.c
|
||||
+++ b/blockdev.c
|
||||
@@ -3043,7 +3043,7 @@ static int pvebackup_dump_cb(void *opaque, BlockBackend *target,
|
||||
buf, &zero_bytes);
|
||||
if (ret < 0) {
|
||||
if (!backup_state.error) {
|
||||
- error_setg(&backup_state.error, "vma_writer_write error %d", ret);
|
||||
+ vma_writer_error_propagate(backup_state.vmaw, &backup_state.error);
|
||||
}
|
||||
if (di->bs && di->bs->job) {
|
||||
block_job_cancel(di->bs->job);
|
||||
diff --git a/vma-writer.c b/vma-writer.c
|
||||
index b0cf529125..689e988423 100644
|
||||
--- a/vma-writer.c
|
||||
+++ b/vma-writer.c
|
||||
@@ -792,6 +792,13 @@ vma_writer_write(VmaWriter *vmaw, uint8_t dev_id, int64_t cluster_num,
|
||||
return transferred;
|
||||
}
|
||||
|
||||
+void vma_writer_error_propagate(VmaWriter *vmaw, Error **errp)
|
||||
+{
|
||||
+ if (vmaw->status < 0 && *errp == NULL) {
|
||||
+ error_setg(errp, "%s", vmaw->errmsg);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
int vma_writer_close(VmaWriter *vmaw, Error **errp)
|
||||
{
|
||||
g_assert(vmaw != NULL);
|
||||
diff --git a/vma.h b/vma.h
|
||||
index 9bb6ea4f69..98377e473e 100644
|
||||
--- a/vma.h
|
||||
+++ b/vma.h
|
||||
@@ -116,6 +116,7 @@ typedef struct VmaDeviceInfo {
|
||||
|
||||
VmaWriter *vma_writer_create(const char *filename, uuid_t uuid, Error **errp);
|
||||
int vma_writer_close(VmaWriter *vmaw, Error **errp);
|
||||
+void vma_writer_error_propagate(VmaWriter *vmaw, Error **errp);
|
||||
void vma_writer_destroy(VmaWriter *vmaw);
|
||||
int vma_writer_add_config(VmaWriter *vmaw, const char *name, gpointer data,
|
||||
size_t len);
|
||||
--
|
||||
2.11.0
|
||||
|
@ -1,7 +1,7 @@
|
||||
From 2727cb752e676e4ef0b9364036879212210cf641 Mon Sep 17 00:00:00 2001
|
||||
From 0b8732d8e19f69471e2f9b8c9a654de62482915a Mon Sep 17 00:00:00 2001
|
||||
From: Thomas Lamprecht <t.lamprecht@proxmox.com>
|
||||
Date: Wed, 6 Apr 2016 16:45:15 +0200
|
||||
Subject: [PATCH 35/49] fix possible unitialised return value
|
||||
Subject: [PATCH 18/28] migrate: fix possible unitialised return value
|
||||
|
||||
---
|
||||
migration/savevm.c | 2 +-
|
@ -1,317 +0,0 @@
|
||||
From 8847efb5dee0b82e397ed7dfb05eec41c28d916d Mon Sep 17 00:00:00 2001
|
||||
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
|
||||
Date: Wed, 9 Dec 2015 15:40:00 +0100
|
||||
Subject: [PATCH 19/49] backup: vma: remove async queue
|
||||
|
||||
---
|
||||
blockdev.c | 6 ++
|
||||
vma-writer.c | 179 +++++++++++------------------------------------------------
|
||||
2 files changed, 38 insertions(+), 147 deletions(-)
|
||||
|
||||
diff --git a/blockdev.c b/blockdev.c
|
||||
index d3aef2cc83..bad5b2a8b8 100644
|
||||
--- a/blockdev.c
|
||||
+++ b/blockdev.c
|
||||
@@ -3122,6 +3122,11 @@ static void pvebackup_cancel(void *opaque)
|
||||
error_setg(&backup_state.error, "backup cancelled");
|
||||
}
|
||||
|
||||
+ if (backup_state.vmaw) {
|
||||
+ /* make sure vma writer does not block anymore */
|
||||
+ vma_writer_set_error(backup_state.vmaw, "backup cancelled");
|
||||
+ }
|
||||
+
|
||||
/* drain all i/o (awake jobs waiting for aio) */
|
||||
bdrv_drain_all();
|
||||
|
||||
@@ -3134,6 +3139,7 @@ static void pvebackup_cancel(void *opaque)
|
||||
if (job) {
|
||||
if (!di->completed) {
|
||||
block_job_cancel_sync(job);
|
||||
+ bdrv_drain_all(); /* drain all i/o (awake jobs waiting for aio) */
|
||||
}
|
||||
}
|
||||
}
|
||||
diff --git a/vma-writer.c b/vma-writer.c
|
||||
index 689e988423..ec8da5378d 100644
|
||||
--- a/vma-writer.c
|
||||
+++ b/vma-writer.c
|
||||
@@ -28,14 +28,8 @@
|
||||
do { if (DEBUG_VMA) { printf("vma: " fmt, ## __VA_ARGS__); } } while (0)
|
||||
|
||||
#define WRITE_BUFFERS 5
|
||||
-
|
||||
-typedef struct VmaAIOCB VmaAIOCB;
|
||||
-struct VmaAIOCB {
|
||||
- unsigned char buffer[VMA_MAX_EXTENT_SIZE];
|
||||
- VmaWriter *vmaw;
|
||||
- size_t bytes;
|
||||
- Coroutine *co;
|
||||
-};
|
||||
+#define HEADER_CLUSTERS 8
|
||||
+#define HEADERBUF_SIZE (VMA_CLUSTER_SIZE*HEADER_CLUSTERS)
|
||||
|
||||
struct VmaWriter {
|
||||
int fd;
|
||||
@@ -47,16 +41,14 @@ struct VmaWriter {
|
||||
bool closed;
|
||||
|
||||
/* we always write extents */
|
||||
- unsigned char outbuf[VMA_MAX_EXTENT_SIZE];
|
||||
+ unsigned char *outbuf;
|
||||
int outbuf_pos; /* in bytes */
|
||||
int outbuf_count; /* in VMA_BLOCKS */
|
||||
uint64_t outbuf_block_info[VMA_BLOCKS_PER_EXTENT];
|
||||
|
||||
- VmaAIOCB *aiocbs[WRITE_BUFFERS];
|
||||
- CoQueue wqueue;
|
||||
+ unsigned char *headerbuf;
|
||||
|
||||
GChecksum *md5csum;
|
||||
- CoMutex writer_lock;
|
||||
CoMutex flush_lock;
|
||||
Coroutine *co_writer;
|
||||
|
||||
@@ -217,38 +209,39 @@ static void vma_co_continue_write(void *opaque)
|
||||
}
|
||||
|
||||
static ssize_t coroutine_fn
|
||||
-vma_co_write(VmaWriter *vmaw, const void *buf, size_t bytes)
|
||||
+vma_queue_write(VmaWriter *vmaw, const void *buf, size_t bytes)
|
||||
{
|
||||
- size_t done = 0;
|
||||
- ssize_t ret;
|
||||
+ DPRINTF("vma_queue_write enter %zd\n", bytes);
|
||||
|
||||
- /* atomic writes (we cannot interleave writes) */
|
||||
- qemu_co_mutex_lock(&vmaw->writer_lock);
|
||||
+ assert(vmaw);
|
||||
+ assert(buf);
|
||||
+ assert(bytes <= VMA_MAX_EXTENT_SIZE);
|
||||
|
||||
- DPRINTF("vma_co_write enter %zd\n", bytes);
|
||||
+ size_t done = 0;
|
||||
+ ssize_t ret;
|
||||
|
||||
assert(vmaw->co_writer == NULL);
|
||||
|
||||
vmaw->co_writer = qemu_coroutine_self();
|
||||
|
||||
- aio_set_fd_handler(qemu_get_aio_context(), vmaw->fd, false, NULL, vma_co_continue_write, vmaw);
|
||||
-
|
||||
- DPRINTF("vma_co_write wait until writable\n");
|
||||
- qemu_coroutine_yield();
|
||||
- DPRINTF("vma_co_write starting %zd\n", bytes);
|
||||
-
|
||||
while (done < bytes) {
|
||||
+ aio_set_fd_handler(qemu_get_aio_context(), vmaw->fd, false, NULL, vma_co_continue_write, NULL, vmaw);
|
||||
+ qemu_coroutine_yield();
|
||||
+ aio_set_fd_handler(qemu_get_aio_context(), vmaw->fd, false, NULL, NULL, NULL, NULL);
|
||||
+ if (vmaw->status < 0) {
|
||||
+ DPRINTF("vma_queue_write detected canceled backup\n");
|
||||
+ done = -1;
|
||||
+ break;
|
||||
+ }
|
||||
ret = write(vmaw->fd, buf + done, bytes - done);
|
||||
if (ret > 0) {
|
||||
done += ret;
|
||||
- DPRINTF("vma_co_write written %zd %zd\n", done, ret);
|
||||
+ DPRINTF("vma_queue_write written %zd %zd\n", done, ret);
|
||||
} else if (ret < 0) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
||||
- DPRINTF("vma_co_write yield %zd\n", done);
|
||||
- qemu_coroutine_yield();
|
||||
- DPRINTF("vma_co_write restart %zd\n", done);
|
||||
- } else {
|
||||
- vma_writer_set_error(vmaw, "vma_co_write write error - %s",
|
||||
+ /* try again */
|
||||
+ } else {
|
||||
+ vma_writer_set_error(vmaw, "vma_queue_write: write error - %s",
|
||||
g_strerror(errno));
|
||||
done = -1; /* always return failure for partial writes */
|
||||
break;
|
||||
@@ -258,102 +251,9 @@ vma_co_write(VmaWriter *vmaw, const void *buf, size_t bytes)
|
||||
}
|
||||
}
|
||||
|
||||
- aio_set_fd_handler(qemu_get_aio_context(), vmaw->fd, false, NULL, NULL, NULL);
|
||||
-
|
||||
vmaw->co_writer = NULL;
|
||||
-
|
||||
- qemu_co_mutex_unlock(&vmaw->writer_lock);
|
||||
-
|
||||
- DPRINTF("vma_co_write leave %zd\n", done);
|
||||
- return done;
|
||||
-}
|
||||
-
|
||||
-static void coroutine_fn vma_co_writer_task(void *opaque)
|
||||
-{
|
||||
- VmaAIOCB *cb = opaque;
|
||||
-
|
||||
- DPRINTF("vma_co_writer_task start\n");
|
||||
-
|
||||
- int64_t done = vma_co_write(cb->vmaw, cb->buffer, cb->bytes);
|
||||
- DPRINTF("vma_co_writer_task write done %zd\n", done);
|
||||
-
|
||||
- if (done != cb->bytes) {
|
||||
- DPRINTF("vma_co_writer_task failed write %zd %zd", cb->bytes, done);
|
||||
- vma_writer_set_error(cb->vmaw, "vma_co_writer_task failed write %zd",
|
||||
- done);
|
||||
- }
|
||||
-
|
||||
- cb->bytes = 0;
|
||||
-
|
||||
- qemu_co_queue_next(&cb->vmaw->wqueue);
|
||||
-
|
||||
- DPRINTF("vma_co_writer_task end\n");
|
||||
-}
|
||||
-
|
||||
-static void coroutine_fn vma_queue_flush(VmaWriter *vmaw)
|
||||
-{
|
||||
- DPRINTF("vma_queue_flush enter\n");
|
||||
-
|
||||
- assert(vmaw);
|
||||
-
|
||||
- while (1) {
|
||||
- int i;
|
||||
- VmaAIOCB *cb = NULL;
|
||||
- for (i = 0; i < WRITE_BUFFERS; i++) {
|
||||
- if (vmaw->aiocbs[i]->bytes) {
|
||||
- cb = vmaw->aiocbs[i];
|
||||
- DPRINTF("FOUND USED AIO BUFFER %d %zd\n", i,
|
||||
- vmaw->aiocbs[i]->bytes);
|
||||
- break;
|
||||
- }
|
||||
- }
|
||||
- if (!cb) {
|
||||
- break;
|
||||
- }
|
||||
- qemu_co_queue_wait(&vmaw->wqueue);
|
||||
- }
|
||||
-
|
||||
- DPRINTF("vma_queue_flush leave\n");
|
||||
-}
|
||||
-
|
||||
-/**
|
||||
- * NOTE: pipe buffer size in only 4096 bytes on linux (see 'ulimit -a')
|
||||
- * So we need to create a coroutione to allow 'parallel' execution.
|
||||
- */
|
||||
-static ssize_t coroutine_fn
|
||||
-vma_queue_write(VmaWriter *vmaw, const void *buf, size_t bytes)
|
||||
-{
|
||||
- DPRINTF("vma_queue_write enter %zd\n", bytes);
|
||||
-
|
||||
- assert(vmaw);
|
||||
- assert(buf);
|
||||
- assert(bytes <= VMA_MAX_EXTENT_SIZE);
|
||||
-
|
||||
- VmaAIOCB *cb = NULL;
|
||||
- while (!cb) {
|
||||
- int i;
|
||||
- for (i = 0; i < WRITE_BUFFERS; i++) {
|
||||
- if (!vmaw->aiocbs[i]->bytes) {
|
||||
- cb = vmaw->aiocbs[i];
|
||||
- break;
|
||||
- }
|
||||
- }
|
||||
- if (!cb) {
|
||||
- qemu_co_queue_wait(&vmaw->wqueue);
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- memcpy(cb->buffer, buf, bytes);
|
||||
- cb->bytes = bytes;
|
||||
- cb->vmaw = vmaw;
|
||||
-
|
||||
- DPRINTF("vma_queue_write start %zd\n", bytes);
|
||||
- cb->co = qemu_coroutine_create(vma_co_writer_task);
|
||||
- qemu_coroutine_enter(cb->co, cb);
|
||||
-
|
||||
- DPRINTF("vma_queue_write leave\n");
|
||||
-
|
||||
- return bytes;
|
||||
+
|
||||
+ return (done == bytes) ? bytes : -1;
|
||||
}
|
||||
|
||||
VmaWriter *vma_writer_create(const char *filename, uuid_t uuid, Error **errp)
|
||||
@@ -420,20 +320,16 @@ VmaWriter *vma_writer_create(const char *filename, uuid_t uuid, Error **errp)
|
||||
}
|
||||
|
||||
/* we use O_DIRECT, so we need to align IO buffers */
|
||||
- int i;
|
||||
- for (i = 0; i < WRITE_BUFFERS; i++) {
|
||||
- vmaw->aiocbs[i] = qemu_memalign(512, sizeof(VmaAIOCB));
|
||||
- memset(vmaw->aiocbs[i], 0, sizeof(VmaAIOCB));
|
||||
- }
|
||||
+
|
||||
+ vmaw->outbuf = qemu_memalign(512, VMA_MAX_EXTENT_SIZE);
|
||||
+ vmaw->headerbuf = qemu_memalign(512, HEADERBUF_SIZE);
|
||||
|
||||
vmaw->outbuf_count = 0;
|
||||
vmaw->outbuf_pos = VMA_EXTENT_HEADER_SIZE;
|
||||
|
||||
vmaw->header_blob_table_pos = 1; /* start at pos 1 */
|
||||
|
||||
- qemu_co_mutex_init(&vmaw->writer_lock);
|
||||
qemu_co_mutex_init(&vmaw->flush_lock);
|
||||
- qemu_co_queue_init(&vmaw->wqueue);
|
||||
|
||||
uuid_copy(vmaw->uuid, uuid);
|
||||
|
||||
@@ -460,8 +356,7 @@ err:
|
||||
static int coroutine_fn vma_write_header(VmaWriter *vmaw)
|
||||
{
|
||||
assert(vmaw);
|
||||
- int header_clusters = 8;
|
||||
- char buf[65536*header_clusters];
|
||||
+ unsigned char *buf = vmaw->headerbuf;
|
||||
VmaHeader *head = (VmaHeader *)buf;
|
||||
|
||||
int i;
|
||||
@@ -472,7 +367,7 @@ static int coroutine_fn vma_write_header(VmaWriter *vmaw)
|
||||
return vmaw->status;
|
||||
}
|
||||
|
||||
- memset(buf, 0, sizeof(buf));
|
||||
+ memset(buf, 0, HEADERBUF_SIZE);
|
||||
|
||||
head->magic = VMA_MAGIC;
|
||||
head->version = GUINT32_TO_BE(1); /* v1 */
|
||||
@@ -507,7 +402,7 @@ static int coroutine_fn vma_write_header(VmaWriter *vmaw)
|
||||
uint32_t header_size = sizeof(VmaHeader) + vmaw->header_blob_table_size;
|
||||
head->header_size = GUINT32_TO_BE(header_size);
|
||||
|
||||
- if (header_size > sizeof(buf)) {
|
||||
+ if (header_size > HEADERBUF_SIZE) {
|
||||
return -1; /* just to be sure */
|
||||
}
|
||||
|
||||
@@ -805,13 +700,7 @@ int vma_writer_close(VmaWriter *vmaw, Error **errp)
|
||||
|
||||
int i;
|
||||
|
||||
- vma_queue_flush(vmaw);
|
||||
-
|
||||
- /* this should not happen - just to be sure */
|
||||
- while (!qemu_co_queue_empty(&vmaw->wqueue)) {
|
||||
- DPRINTF("vma_writer_close wait\n");
|
||||
- co_aio_sleep_ns(qemu_get_aio_context(), QEMU_CLOCK_REALTIME, 1000000);
|
||||
- }
|
||||
+ assert(vmaw->co_writer == NULL);
|
||||
|
||||
if (vmaw->cmd) {
|
||||
if (pclose(vmaw->cmd) < 0) {
|
||||
@@ -869,9 +758,5 @@ void vma_writer_destroy(VmaWriter *vmaw)
|
||||
g_checksum_free(vmaw->md5csum);
|
||||
}
|
||||
|
||||
- for (i = 0; i < WRITE_BUFFERS; i++) {
|
||||
- free(vmaw->aiocbs[i]);
|
||||
- }
|
||||
-
|
||||
g_free(vmaw);
|
||||
}
|
||||
--
|
||||
2.11.0
|
||||
|
@ -1,8 +1,8 @@
|
||||
From 26fafa2ddc6257bf3aa0ea0e19505e3f0108172d Mon Sep 17 00:00:00 2001
|
||||
From b0603dbd9bd127305472e8162e9b3289b866b824 Mon Sep 17 00:00:00 2001
|
||||
From: Alexandre Derumier <aderumier@odiso.com>
|
||||
Date: Tue, 26 Jul 2016 16:51:00 +0200
|
||||
Subject: [PATCH 39/49] rbd: disable rbd_cache_writethrough_until_flush with
|
||||
cache=unsafe
|
||||
Subject: [PATCH 19/28] block: rbd: disable rbd_cache_writethrough_until_flush
|
||||
with cache=unsafe
|
||||
|
||||
Signed-off-by: Alexandre Derumier <aderumier@odiso.com>
|
||||
---
|
@ -1,56 +0,0 @@
|
||||
From 7708c32e3a14860c519ab3540a50e24a314bb3fa Mon Sep 17 00:00:00 2001
|
||||
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
|
||||
Date: Wed, 9 Dec 2015 15:40:42 +0100
|
||||
Subject: [PATCH 20/49] backup: vma: run flush inside coroutine
|
||||
|
||||
---
|
||||
blockdev.c | 10 +++++++++-
|
||||
vma-writer.c | 4 ++++
|
||||
2 files changed, 13 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/blockdev.c b/blockdev.c
|
||||
index bad5b2a8b8..77ee7ff93b 100644
|
||||
--- a/blockdev.c
|
||||
+++ b/blockdev.c
|
||||
@@ -3087,6 +3087,13 @@ static void pvebackup_cleanup(void)
|
||||
}
|
||||
}
|
||||
|
||||
+static void coroutine_fn backup_close_vma_stream(void *opaque)
|
||||
+{
|
||||
+ PVEBackupDevInfo *di = opaque;
|
||||
+
|
||||
+ vma_writer_close_stream(backup_state.vmaw, di->dev_id);
|
||||
+}
|
||||
+
|
||||
static void pvebackup_complete_cb(void *opaque, int ret)
|
||||
{
|
||||
PVEBackupDevInfo *di = opaque;
|
||||
@@ -3104,7 +3111,8 @@ static void pvebackup_complete_cb(void *opaque, int ret)
|
||||
di->target = NULL;
|
||||
|
||||
if (backup_state.vmaw) {
|
||||
- vma_writer_close_stream(backup_state.vmaw, di->dev_id);
|
||||
+ Coroutine *co = qemu_coroutine_create(backup_close_vma_stream, di);
|
||||
+ qemu_coroutine_enter(co);
|
||||
}
|
||||
|
||||
block_job_cb(bs, ret);
|
||||
diff --git a/vma-writer.c b/vma-writer.c
|
||||
index ec8da5378d..216577a4f7 100644
|
||||
--- a/vma-writer.c
|
||||
+++ b/vma-writer.c
|
||||
@@ -700,6 +700,10 @@ int vma_writer_close(VmaWriter *vmaw, Error **errp)
|
||||
|
||||
int i;
|
||||
|
||||
+ while (vmaw->co_writer) {
|
||||
+ aio_poll(qemu_get_aio_context(), true);
|
||||
+ }
|
||||
+
|
||||
assert(vmaw->co_writer == NULL);
|
||||
|
||||
if (vmaw->cmd) {
|
||||
--
|
||||
2.11.0
|
||||
|
@ -1,7 +1,7 @@
|
||||
From 26b8ed17e06e00b287352b95212d46ff4261e70b Mon Sep 17 00:00:00 2001
|
||||
From 976296684d224ab866fc8b7ebe0d2de4b5b39170 Mon Sep 17 00:00:00 2001
|
||||
From: Alexandre Derumier <aderumier@odiso.com>
|
||||
Date: Tue, 13 Sep 2016 01:57:56 +0200
|
||||
Subject: [PATCH 42/49] qmp_snapshot_drive: add aiocontext
|
||||
Subject: [PATCH 20/28] block: snapshot: qmp_snapshot_drive: add aiocontext
|
||||
|
||||
Signed-off-by: Alexandre Derumier <aderumier@odiso.com>
|
||||
---
|
||||
@ -9,10 +9,10 @@ Signed-off-by: Alexandre Derumier <aderumier@odiso.com>
|
||||
1 file changed, 11 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/savevm-async.c b/savevm-async.c
|
||||
index 2f4766cf6c..5913a905d8 100644
|
||||
index 624e3a34b4..95995eab31 100644
|
||||
--- a/savevm-async.c
|
||||
+++ b/savevm-async.c
|
||||
@@ -345,6 +345,7 @@ void qmp_snapshot_drive(const char *device, const char *name, Error **errp)
|
||||
@@ -377,6 +377,7 @@ void qmp_snapshot_drive(const char *device, const char *name, Error **errp)
|
||||
BlockBackend *blk;
|
||||
BlockDriverState *bs;
|
||||
QEMUSnapshotInfo sn1, *sn = &sn1;
|
||||
@ -20,7 +20,7 @@ index 2f4766cf6c..5913a905d8 100644
|
||||
int ret;
|
||||
#ifdef _WIN32
|
||||
struct _timeb tb;
|
||||
@@ -371,20 +372,23 @@ void qmp_snapshot_drive(const char *device, const char *name, Error **errp)
|
||||
@@ -403,20 +404,23 @@ void qmp_snapshot_drive(const char *device, const char *name, Error **errp)
|
||||
return;
|
||||
}
|
||||
|
||||
@ -47,7 +47,7 @@ index 2f4766cf6c..5913a905d8 100644
|
||||
}
|
||||
|
||||
sn = &sn1;
|
||||
@@ -409,8 +413,11 @@ void qmp_snapshot_drive(const char *device, const char *name, Error **errp)
|
||||
@@ -441,8 +445,11 @@ void qmp_snapshot_drive(const char *device, const char *name, Error **errp)
|
||||
if (ret < 0) {
|
||||
error_set(errp, ERROR_CLASS_GENERIC_ERROR,
|
||||
"Error while creating snapshot on '%s'\n", device);
|
@ -1,36 +0,0 @@
|
||||
From fbb5d5b954df75a366110c2df3bb0685ebfca145 Mon Sep 17 00:00:00 2001
|
||||
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
|
||||
Date: Wed, 9 Dec 2015 15:41:13 +0100
|
||||
Subject: [PATCH 21/49] backup: do not use bdrv_drain_all
|
||||
|
||||
---
|
||||
blockdev.c | 6 +-----
|
||||
1 file changed, 1 insertion(+), 5 deletions(-)
|
||||
|
||||
diff --git a/blockdev.c b/blockdev.c
|
||||
index 77ee7ff93b..2713585051 100644
|
||||
--- a/blockdev.c
|
||||
+++ b/blockdev.c
|
||||
@@ -3135,9 +3135,6 @@ static void pvebackup_cancel(void *opaque)
|
||||
vma_writer_set_error(backup_state.vmaw, "backup cancelled");
|
||||
}
|
||||
|
||||
- /* drain all i/o (awake jobs waiting for aio) */
|
||||
- bdrv_drain_all();
|
||||
-
|
||||
GList *l = backup_state.di_list;
|
||||
while (l) {
|
||||
PVEBackupDevInfo *di = (PVEBackupDevInfo *)l->data;
|
||||
@@ -3146,8 +3143,7 @@ static void pvebackup_cancel(void *opaque)
|
||||
BlockJob *job = di->bs->job;
|
||||
if (job) {
|
||||
if (!di->completed) {
|
||||
- block_job_cancel_sync(job);
|
||||
- bdrv_drain_all(); /* drain all i/o (awake jobs waiting for aio) */
|
||||
+ block_job_cancel_sync(job);
|
||||
}
|
||||
}
|
||||
}
|
||||
--
|
||||
2.11.0
|
||||
|
@ -1,7 +1,8 @@
|
||||
From fe00763cb7556dfdd8fdf4b6f4cc269c291d6bfa Mon Sep 17 00:00:00 2001
|
||||
From 1540187ba7716d502908a1815298d7c3fc8db6a6 Mon Sep 17 00:00:00 2001
|
||||
From: Alexandre Derumier <aderumier@odiso.com>
|
||||
Date: Mon, 7 Nov 2016 11:47:50 +0100
|
||||
Subject: [PATCH 45/49] qmp_delete_drive_snapshot : add aiocontext
|
||||
Subject: [PATCH 21/28] block: snapshot: qmp_delete_drive_snapshot : add
|
||||
aiocontext
|
||||
|
||||
this fix snapshot delete of qcow2 with iothread enabled
|
||||
|
||||
@ -11,10 +12,10 @@ Signed-off-by: Alexandre Derumier <aderumier@odiso.com>
|
||||
1 file changed, 10 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/savevm-async.c b/savevm-async.c
|
||||
index 5913a905d8..3adf89fdb2 100644
|
||||
index 95995eab31..9f839faab5 100644
|
||||
--- a/savevm-async.c
|
||||
+++ b/savevm-async.c
|
||||
@@ -427,6 +427,7 @@ void qmp_delete_drive_snapshot(const char *device, const char *name,
|
||||
@@ -459,6 +459,7 @@ void qmp_delete_drive_snapshot(const char *device, const char *name,
|
||||
BlockDriverState *bs;
|
||||
QEMUSnapshotInfo sn1, *sn = &sn1;
|
||||
Error *local_err = NULL;
|
||||
@ -22,7 +23,7 @@ index 5913a905d8..3adf89fdb2 100644
|
||||
|
||||
int ret;
|
||||
|
||||
@@ -443,22 +444,28 @@ void qmp_delete_drive_snapshot(const char *device, const char *name,
|
||||
@@ -475,22 +476,28 @@ void qmp_delete_drive_snapshot(const char *device, const char *name,
|
||||
return;
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
From f6d6cb162d0cdce8b3d83b0af7772fcd63f1dafe Mon Sep 17 00:00:00 2001
|
||||
From 26129edb715505ae35207eff2477cffec50af13e Mon Sep 17 00:00:00 2001
|
||||
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
|
||||
Date: Mon, 24 Oct 2016 09:32:36 +0200
|
||||
Subject: [PATCH 44/49] glusterfs: no default logfile if daemonized
|
||||
Subject: [PATCH 22/28] glusterfs: no default logfile if daemonized
|
||||
|
||||
---
|
||||
block/gluster.c | 15 +++++++++++----
|
@ -1,256 +0,0 @@
|
||||
From 84631ae35b99f60a08a4a02f1596f5c9d17ebff0 Mon Sep 17 00:00:00 2001
|
||||
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
|
||||
Date: Wed, 9 Dec 2015 16:31:51 +0100
|
||||
Subject: [PATCH 23/49] backup: vma: allow empty backups
|
||||
|
||||
---
|
||||
vma-reader.c | 29 ++++++++++++-------------
|
||||
vma-writer.c | 30 ++++++++++++++++----------
|
||||
vma.c | 70 ++++++++++++++++++++++++++++++++++++------------------------
|
||||
vma.h | 1 +
|
||||
4 files changed, 76 insertions(+), 54 deletions(-)
|
||||
|
||||
diff --git a/vma-reader.c b/vma-reader.c
|
||||
index 2aafb26b2a..78f1de9499 100644
|
||||
--- a/vma-reader.c
|
||||
+++ b/vma-reader.c
|
||||
@@ -326,11 +326,6 @@ static int vma_reader_read_head(VmaReader *vmar, Error **errp)
|
||||
}
|
||||
}
|
||||
|
||||
- if (!count) {
|
||||
- error_setg(errp, "vma does not contain data");
|
||||
- return -1;
|
||||
- }
|
||||
-
|
||||
for (i = 0; i < VMA_MAX_CONFIGS; i++) {
|
||||
uint32_t name_ptr = GUINT32_FROM_BE(h->config_names[i]);
|
||||
uint32_t data_ptr = GUINT32_FROM_BE(h->config_data[i]);
|
||||
@@ -822,16 +817,20 @@ static int vma_reader_restore_full(VmaReader *vmar, int vmstate_fd,
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
- printf("total bytes read %zd, sparse bytes %zd (%.3g%%)\n",
|
||||
- vmar->clusters_read*VMA_CLUSTER_SIZE,
|
||||
- vmar->zero_cluster_data,
|
||||
- (double)(100.0*vmar->zero_cluster_data)/
|
||||
- (vmar->clusters_read*VMA_CLUSTER_SIZE));
|
||||
-
|
||||
- int64_t datasize = vmar->clusters_read*VMA_CLUSTER_SIZE-vmar->zero_cluster_data;
|
||||
- if (datasize) { // this does not make sense for empty files
|
||||
- printf("space reduction due to 4K zero blocks %.3g%%\n",
|
||||
- (double)(100.0*vmar->partial_zero_cluster_data) / datasize);
|
||||
+ if (vmar->clusters_read) {
|
||||
+ printf("total bytes read %zd, sparse bytes %zd (%.3g%%)\n",
|
||||
+ vmar->clusters_read*VMA_CLUSTER_SIZE,
|
||||
+ vmar->zero_cluster_data,
|
||||
+ (double)(100.0*vmar->zero_cluster_data)/
|
||||
+ (vmar->clusters_read*VMA_CLUSTER_SIZE));
|
||||
+
|
||||
+ int64_t datasize = vmar->clusters_read*VMA_CLUSTER_SIZE-vmar->zero_cluster_data;
|
||||
+ if (datasize) { // this does not make sense for empty files
|
||||
+ printf("space reduction due to 4K zero blocks %.3g%%\n",
|
||||
+ (double)(100.0*vmar->partial_zero_cluster_data) / datasize);
|
||||
+ }
|
||||
+ } else {
|
||||
+ printf("vma archive contains no image data\n");
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
diff --git a/vma-writer.c b/vma-writer.c
|
||||
index 216577a4f7..0dd668b257 100644
|
||||
--- a/vma-writer.c
|
||||
+++ b/vma-writer.c
|
||||
@@ -252,7 +252,7 @@ vma_queue_write(VmaWriter *vmaw, const void *buf, size_t bytes)
|
||||
}
|
||||
|
||||
vmaw->co_writer = NULL;
|
||||
-
|
||||
+
|
||||
return (done == bytes) ? bytes : -1;
|
||||
}
|
||||
|
||||
@@ -376,10 +376,6 @@ static int coroutine_fn vma_write_header(VmaWriter *vmaw)
|
||||
time_t ctime = time(NULL);
|
||||
head->ctime = GUINT64_TO_BE(ctime);
|
||||
|
||||
- if (!vmaw->stream_count) {
|
||||
- return -1;
|
||||
- }
|
||||
-
|
||||
for (i = 0; i < VMA_MAX_CONFIGS; i++) {
|
||||
head->config_names[i] = GUINT32_TO_BE(vmaw->config_names[i]);
|
||||
head->config_data[i] = GUINT32_TO_BE(vmaw->config_data[i]);
|
||||
@@ -496,6 +492,23 @@ static int vma_count_open_streams(VmaWriter *vmaw)
|
||||
return open_drives;
|
||||
}
|
||||
|
||||
+
|
||||
+/**
|
||||
+ * You need to call this if the vma archive does not contain
|
||||
+ * any data stream.
|
||||
+ */
|
||||
+int coroutine_fn
|
||||
+vma_writer_flush_output(VmaWriter *vmaw)
|
||||
+{
|
||||
+ qemu_co_mutex_lock(&vmaw->flush_lock);
|
||||
+ int ret = vma_writer_flush(vmaw);
|
||||
+ qemu_co_mutex_unlock(&vmaw->flush_lock);
|
||||
+ if (ret < 0) {
|
||||
+ vma_writer_set_error(vmaw, "vma_writer_flush_header failed");
|
||||
+ }
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
/**
|
||||
* all jobs should call this when there is no more data
|
||||
* Returns: number of remaining stream (0 ==> finished)
|
||||
@@ -523,12 +536,7 @@ vma_writer_close_stream(VmaWriter *vmaw, uint8_t dev_id)
|
||||
|
||||
if (open_drives <= 0) {
|
||||
DPRINTF("vma_writer_set_status all drives completed\n");
|
||||
- qemu_co_mutex_lock(&vmaw->flush_lock);
|
||||
- int ret = vma_writer_flush(vmaw);
|
||||
- qemu_co_mutex_unlock(&vmaw->flush_lock);
|
||||
- if (ret < 0) {
|
||||
- vma_writer_set_error(vmaw, "vma_writer_close_stream: flush failed");
|
||||
- }
|
||||
+ vma_writer_flush_output(vmaw);
|
||||
}
|
||||
|
||||
return open_drives;
|
||||
diff --git a/vma.c b/vma.c
|
||||
index 1ffaced897..c7c05385f6 100644
|
||||
--- a/vma.c
|
||||
+++ b/vma.c
|
||||
@@ -28,7 +28,7 @@ static void help(void)
|
||||
"\n"
|
||||
"vma list <filename>\n"
|
||||
"vma config <filename> [-c config]\n"
|
||||
- "vma create <filename> [-c config] <archive> pathname ...\n"
|
||||
+ "vma create <filename> [-c config] pathname ...\n"
|
||||
"vma extract <filename> [-r <fifo>] <targetdir>\n"
|
||||
"vma verify <filename> [-v]\n"
|
||||
;
|
||||
@@ -396,6 +396,18 @@ typedef struct BackupJob {
|
||||
|
||||
#define BACKUP_SECTORS_PER_CLUSTER (VMA_CLUSTER_SIZE / BDRV_SECTOR_SIZE)
|
||||
|
||||
+static void coroutine_fn backup_run_empty(void *opaque)
|
||||
+{
|
||||
+ VmaWriter *vmaw = (VmaWriter *)opaque;
|
||||
+
|
||||
+ vma_writer_flush_output(vmaw);
|
||||
+
|
||||
+ Error *err = NULL;
|
||||
+ if (vma_writer_close(vmaw, &err) != 0) {
|
||||
+ g_warning("vma_writer_close failed %s", error_get_pretty(err));
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static void coroutine_fn backup_run(void *opaque)
|
||||
{
|
||||
BackupJob *job = (BackupJob *)opaque;
|
||||
@@ -469,8 +481,8 @@ static int create_archive(int argc, char **argv)
|
||||
}
|
||||
|
||||
|
||||
- /* make sure we have archive name and at least one path */
|
||||
- if ((optind + 2) > argc) {
|
||||
+ /* make sure we an archive name */
|
||||
+ if ((optind + 1) > argc) {
|
||||
help();
|
||||
}
|
||||
|
||||
@@ -505,11 +517,11 @@ static int create_archive(int argc, char **argv)
|
||||
l = g_list_next(l);
|
||||
}
|
||||
|
||||
- int ind = 0;
|
||||
+ int devcount = 0;
|
||||
while (optind < argc) {
|
||||
const char *path = argv[optind++];
|
||||
char *devname = NULL;
|
||||
- path = extract_devname(path, &devname, ind++);
|
||||
+ path = extract_devname(path, &devname, devcount++);
|
||||
|
||||
Error *errp = NULL;
|
||||
BlockDriverState *bs;
|
||||
@@ -540,37 +552,39 @@ static int create_archive(int argc, char **argv)
|
||||
int percent = 0;
|
||||
int last_percent = -1;
|
||||
|
||||
- while (1) {
|
||||
- main_loop_wait(false);
|
||||
- vma_writer_get_status(vmaw, &vmastat);
|
||||
+ if (devcount) {
|
||||
+ while (1) {
|
||||
+ main_loop_wait(false);
|
||||
+ vma_writer_get_status(vmaw, &vmastat);
|
||||
+
|
||||
+ if (verbose) {
|
||||
|
||||
- if (verbose) {
|
||||
+ uint64_t total = 0;
|
||||
+ uint64_t transferred = 0;
|
||||
+ uint64_t zero_bytes = 0;
|
||||
|
||||
- uint64_t total = 0;
|
||||
- uint64_t transferred = 0;
|
||||
- uint64_t zero_bytes = 0;
|
||||
+ int i;
|
||||
+ for (i = 0; i < 256; i++) {
|
||||
+ if (vmastat.stream_info[i].size) {
|
||||
+ total += vmastat.stream_info[i].size;
|
||||
+ transferred += vmastat.stream_info[i].transferred;
|
||||
+ zero_bytes += vmastat.stream_info[i].zero_bytes;
|
||||
+ }
|
||||
+ }
|
||||
+ percent = (transferred*100)/total;
|
||||
+ if (percent != last_percent) {
|
||||
+ fprintf(stderr, "progress %d%% %zd/%zd %zd\n", percent,
|
||||
+ transferred, total, zero_bytes);
|
||||
+ fflush(stderr);
|
||||
|
||||
- int i;
|
||||
- for (i = 0; i < 256; i++) {
|
||||
- if (vmastat.stream_info[i].size) {
|
||||
- total += vmastat.stream_info[i].size;
|
||||
- transferred += vmastat.stream_info[i].transferred;
|
||||
- zero_bytes += vmastat.stream_info[i].zero_bytes;
|
||||
+ last_percent = percent;
|
||||
}
|
||||
}
|
||||
- percent = (transferred*100)/total;
|
||||
- if (percent != last_percent) {
|
||||
- fprintf(stderr, "progress %d%% %zd/%zd %zd\n", percent,
|
||||
- transferred, total, zero_bytes);
|
||||
- fflush(stderr);
|
||||
|
||||
- last_percent = percent;
|
||||
+ if (vmastat.closed) {
|
||||
+ break;
|
||||
}
|
||||
}
|
||||
-
|
||||
- if (vmastat.closed) {
|
||||
- break;
|
||||
- }
|
||||
} else {
|
||||
Coroutine *co = qemu_coroutine_create(backup_run_empty, vmaw);
|
||||
qemu_coroutine_enter(co);
|
||||
diff --git a/vma.h b/vma.h
|
||||
index 98377e473e..365ceb2bcb 100644
|
||||
--- a/vma.h
|
||||
+++ b/vma.h
|
||||
@@ -128,6 +128,7 @@ int64_t coroutine_fn vma_writer_write(VmaWriter *vmaw, uint8_t dev_id,
|
||||
size_t *zero_bytes);
|
||||
|
||||
int coroutine_fn vma_writer_close_stream(VmaWriter *vmaw, uint8_t dev_id);
|
||||
+int coroutine_fn vma_writer_flush_output(VmaWriter *vmaw);
|
||||
|
||||
int vma_writer_get_status(VmaWriter *vmaw, VmaStatus *status);
|
||||
void vma_writer_set_error(VmaWriter *vmaw, const char *fmt, ...);
|
||||
--
|
||||
2.11.0
|
||||
|
@ -1,7 +1,7 @@
|
||||
From 42c448d4ae35e5531023dff7ed07eb0135b3a2a2 Mon Sep 17 00:00:00 2001
|
||||
From 113e86e08a88805de1fb3aa88327174c8fa1d437 Mon Sep 17 00:00:00 2001
|
||||
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
|
||||
Date: Wed, 30 Nov 2016 10:27:47 +0100
|
||||
Subject: [PATCH 47/49] glusterfs: allow partial reads
|
||||
Subject: [PATCH 23/28] glusterfs: allow partial reads
|
||||
|
||||
This should deal with qemu bug #1644754 until upstream
|
||||
decides which way to go. The general direction seems to be
|
@ -1,12 +1,12 @@
|
||||
From bdaf742bcf995c0c3f73b2e61d34b8a85199f472 Mon Sep 17 00:00:00 2001
|
||||
From f5ec823838e35470f0c9ff6bf7968ac02fa08b4d Mon Sep 17 00:00:00 2001
|
||||
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
|
||||
Date: Thu, 17 Mar 2016 11:33:37 +0100
|
||||
Subject: [PATCH 33/49] block: add the zeroinit block driver filter
|
||||
Subject: [PATCH 24/28] block: add the zeroinit block driver filter
|
||||
|
||||
---
|
||||
block/Makefile.objs | 1 +
|
||||
block/zeroinit.c | 219 ++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 220 insertions(+)
|
||||
block/zeroinit.c | 220 ++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 221 insertions(+)
|
||||
create mode 100644 block/zeroinit.c
|
||||
|
||||
diff --git a/block/Makefile.objs b/block/Makefile.objs
|
||||
@ -23,10 +23,10 @@ index de96f8ee80..8cdac08db5 100644
|
||||
block-obj-$(CONFIG_WIN32) += file-win32.o win32-aio.o
|
||||
diff --git a/block/zeroinit.c b/block/zeroinit.c
|
||||
new file mode 100644
|
||||
index 0000000000..0a8c7f9622
|
||||
index 0000000000..a857ec3c62
|
||||
--- /dev/null
|
||||
+++ b/block/zeroinit.c
|
||||
@@ -0,0 +1,219 @@
|
||||
@@ -0,0 +1,220 @@
|
||||
+/*
|
||||
+ * Filter to fake a zero-initialized block device.
|
||||
+ *
|
||||
@ -220,6 +220,7 @@ index 0000000000..0a8c7f9622
|
||||
+ .bdrv_file_open = zeroinit_open,
|
||||
+ .bdrv_close = zeroinit_close,
|
||||
+ .bdrv_getlength = zeroinit_getlength,
|
||||
+ .bdrv_child_perm = bdrv_filter_default_perms,
|
||||
+ .bdrv_co_flush_to_disk = zeroinit_co_flush,
|
||||
+
|
||||
+ .bdrv_co_pwrite_zeroes = zeroinit_co_pwrite_zeroes,
|
@ -1,7 +1,7 @@
|
||||
From 70bc584282901ee2a8954559393f305377016249 Mon Sep 17 00:00:00 2001
|
||||
From 3bd6a30a92ecb420bac469ec977fbcc0ad918d1c Mon Sep 17 00:00:00 2001
|
||||
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
|
||||
Date: Fri, 23 Jun 2017 12:01:43 +0200
|
||||
Subject: [PATCH 50/50] qemu-img dd: add osize and read from/to stdin/stdout
|
||||
Subject: [PATCH 25/28] qemu-img dd: add osize and read from/to stdin/stdout
|
||||
|
||||
Neither convert nor dd were previously able to write to or
|
||||
read from a pipe. Particularly serializing an image file
|
||||
@ -30,9 +30,26 @@ override the output file's size.
|
||||
|
||||
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
|
||||
---
|
||||
qemu-img.c | 176 +++++++++++++++++++++++++++++++++++++++----------------------
|
||||
1 file changed, 113 insertions(+), 63 deletions(-)
|
||||
qemu-img-cmds.hx | 4 +-
|
||||
qemu-img.c | 176 +++++++++++++++++++++++++++++++++++--------------------
|
||||
2 files changed, 115 insertions(+), 65 deletions(-)
|
||||
|
||||
diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx
|
||||
index 8ac78222af..16bee83987 100644
|
||||
--- a/qemu-img-cmds.hx
|
||||
+++ b/qemu-img-cmds.hx
|
||||
@@ -46,9 +46,9 @@ STEXI
|
||||
ETEXI
|
||||
|
||||
DEF("dd", img_dd,
|
||||
- "dd [--image-opts] [-f fmt] [-O output_fmt] [bs=block_size] [count=blocks] [skip=blocks] if=input of=output")
|
||||
+ "dd [--image-opts] [-f fmt] [-O output_fmt] [bs=block_size] [count=blocks] [skip=blocks] [osize=output_size] [if=input] [of=output]")
|
||||
STEXI
|
||||
-@item dd [--image-opts] [-f @var{fmt}] [-O @var{output_fmt}] [bs=@var{block_size}] [count=@var{blocks}] [skip=@var{blocks}] if=@var{input} of=@var{output}
|
||||
+@item dd [--image-opts] [-f @var{fmt}] [-O @var{output_fmt}] [bs=@var{block_size}] [count=@var{blocks}] [skip=@var{blocks}] [osize=output_size] [if=@var{input}] [of=@var{output}]
|
||||
ETEXI
|
||||
|
||||
DEF("info", img_info,
|
||||
diff --git a/qemu-img.c b/qemu-img.c
|
||||
index 4f7f458dd2..b9d1ef7bb8 100644
|
||||
--- a/qemu-img.c
|
100
debian/patches/pve/0026-backup-modify-job-api.patch
vendored
Normal file
100
debian/patches/pve/0026-backup-modify-job-api.patch
vendored
Normal file
@ -0,0 +1,100 @@
|
||||
From 020e2108f7571fac3853c47ba1ea8bafb5eef81e Mon Sep 17 00:00:00 2001
|
||||
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
|
||||
Date: Wed, 9 Dec 2015 15:04:57 +0100
|
||||
Subject: [PATCH 26/28] backup: modify job api
|
||||
|
||||
Introduce a pause_count parameter to start a backup in
|
||||
paused mode. This way backups of multiple drives can be
|
||||
started up sequentially via the completion callback while
|
||||
having been started at the same point in time.
|
||||
---
|
||||
block/backup.c | 2 ++
|
||||
block/replication.c | 2 +-
|
||||
blockdev.c | 4 ++--
|
||||
blockjob.c | 2 +-
|
||||
include/block/block_int.h | 1 +
|
||||
5 files changed, 7 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/block/backup.c b/block/backup.c
|
||||
index a4fb2884f9..1ede70c061 100644
|
||||
--- a/block/backup.c
|
||||
+++ b/block/backup.c
|
||||
@@ -558,6 +558,7 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
|
||||
BlockdevOnError on_target_error,
|
||||
int creation_flags,
|
||||
BlockCompletionFunc *cb, void *opaque,
|
||||
+ int pause_count,
|
||||
BlockJobTxn *txn, Error **errp)
|
||||
{
|
||||
int64_t len;
|
||||
@@ -682,6 +683,7 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
|
||||
block_job_add_bdrv(&job->common, "target", target, 0, BLK_PERM_ALL,
|
||||
&error_abort);
|
||||
job->common.len = len;
|
||||
+ job->common.pause_count = pause_count;
|
||||
block_job_txn_add_job(txn, &job->common);
|
||||
|
||||
return &job->common;
|
||||
diff --git a/block/replication.c b/block/replication.c
|
||||
index bf3c395eb4..1c41d9e6bf 100644
|
||||
--- a/block/replication.c
|
||||
+++ b/block/replication.c
|
||||
@@ -531,7 +531,7 @@ static void replication_start(ReplicationState *rs, ReplicationMode mode,
|
||||
0, MIRROR_SYNC_MODE_NONE, NULL, false,
|
||||
BLOCKDEV_ON_ERROR_REPORT,
|
||||
BLOCKDEV_ON_ERROR_REPORT, BLOCK_JOB_INTERNAL,
|
||||
- backup_job_completed, bs, NULL, &local_err);
|
||||
+ backup_job_completed, bs, 0, NULL, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
backup_job_cleanup(bs);
|
||||
diff --git a/blockdev.c b/blockdev.c
|
||||
index 4927914ce3..ec5e931029 100644
|
||||
--- a/blockdev.c
|
||||
+++ b/blockdev.c
|
||||
@@ -3273,7 +3273,7 @@ static BlockJob *do_drive_backup(DriveBackup *backup, BlockJobTxn *txn,
|
||||
job = backup_job_create(backup->job_id, bs, target_bs, backup->speed,
|
||||
backup->sync, bmap, backup->compress,
|
||||
backup->on_source_error, backup->on_target_error,
|
||||
- BLOCK_JOB_DEFAULT, NULL, NULL, txn, &local_err);
|
||||
+ BLOCK_JOB_DEFAULT, NULL, NULL, 0, txn, &local_err);
|
||||
bdrv_unref(target_bs);
|
||||
if (local_err != NULL) {
|
||||
error_propagate(errp, local_err);
|
||||
@@ -3352,7 +3352,7 @@ BlockJob *do_blockdev_backup(BlockdevBackup *backup, BlockJobTxn *txn,
|
||||
job = backup_job_create(backup->job_id, bs, target_bs, backup->speed,
|
||||
backup->sync, NULL, backup->compress,
|
||||
backup->on_source_error, backup->on_target_error,
|
||||
- BLOCK_JOB_DEFAULT, NULL, NULL, txn, &local_err);
|
||||
+ BLOCK_JOB_DEFAULT, NULL, NULL, 0, txn, &local_err);
|
||||
if (local_err != NULL) {
|
||||
error_propagate(errp, local_err);
|
||||
}
|
||||
diff --git a/blockjob.c b/blockjob.c
|
||||
index 6e489327ff..764d41863e 100644
|
||||
--- a/blockjob.c
|
||||
+++ b/blockjob.c
|
||||
@@ -289,7 +289,7 @@ void block_job_start(BlockJob *job)
|
||||
job->co = qemu_coroutine_create(block_job_co_entry, job);
|
||||
job->pause_count--;
|
||||
job->busy = true;
|
||||
- job->paused = false;
|
||||
+ job->paused = job->pause_count > 0;
|
||||
bdrv_coroutine_enter(blk_bs(job->blk), job->co);
|
||||
}
|
||||
|
||||
diff --git a/include/block/block_int.h b/include/block/block_int.h
|
||||
index 59400bd848..2b3ecd0575 100644
|
||||
--- a/include/block/block_int.h
|
||||
+++ b/include/block/block_int.h
|
||||
@@ -878,6 +878,7 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
|
||||
BlockdevOnError on_target_error,
|
||||
int creation_flags,
|
||||
BlockCompletionFunc *cb, void *opaque,
|
||||
+ int pause_count,
|
||||
BlockJobTxn *txn, Error **errp);
|
||||
|
||||
void hmp_drive_add_node(Monitor *mon, const char *optstr);
|
||||
--
|
||||
2.11.0
|
||||
|
1400
debian/patches/pve/0027-backup-introduce-vma-archive-format.patch
vendored
Normal file
1400
debian/patches/pve/0027-backup-introduce-vma-archive-format.patch
vendored
Normal file
File diff suppressed because it is too large
Load Diff
144
debian/patches/pve/0027-vma-add-firewall.patch
vendored
144
debian/patches/pve/0027-vma-add-firewall.patch
vendored
@ -1,144 +0,0 @@
|
||||
From 23aa2199f34c16254bd342abbd3ae2b16e4aa64e Mon Sep 17 00:00:00 2001
|
||||
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
|
||||
Date: Wed, 9 Dec 2015 16:51:23 +0100
|
||||
Subject: [PATCH 27/49] vma: add firewall
|
||||
|
||||
---
|
||||
blockdev.c | 78 ++++++++++++++++++++++++++++++++++----------------------
|
||||
hmp.c | 2 +-
|
||||
qapi-schema.json | 1 +
|
||||
3 files changed, 50 insertions(+), 31 deletions(-)
|
||||
|
||||
diff --git a/blockdev.c b/blockdev.c
|
||||
index 2713585051..43818dade1 100644
|
||||
--- a/blockdev.c
|
||||
+++ b/blockdev.c
|
||||
@@ -3163,6 +3163,44 @@ void qmp_backup_cancel(Error **errp)
|
||||
}
|
||||
}
|
||||
|
||||
+static int config_to_vma(const char *file, BackupFormat format,
|
||||
+ const char *backup_dir, VmaWriter *vmaw,
|
||||
+ Error **errp)
|
||||
+{
|
||||
+ char *cdata = NULL;
|
||||
+ gsize clen = 0;
|
||||
+ GError *err = NULL;
|
||||
+ if (!g_file_get_contents(file, &cdata, &clen, &err)) {
|
||||
+ error_setg(errp, "unable to read file '%s'", file);
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ char *basename = g_path_get_basename(file);
|
||||
+
|
||||
+ if (format == BACKUP_FORMAT_VMA) {
|
||||
+ if (vma_writer_add_config(vmaw, basename, cdata, clen) != 0) {
|
||||
+ error_setg(errp, "unable to add %s config data to vma archive", file);
|
||||
+ g_free(cdata);
|
||||
+ g_free(basename);
|
||||
+ return 1;
|
||||
+ }
|
||||
+ } else if (format == BACKUP_FORMAT_DIR) {
|
||||
+ char config_path[PATH_MAX];
|
||||
+ snprintf(config_path, PATH_MAX, "%s/%s", backup_dir, basename);
|
||||
+ if (!g_file_set_contents(config_path, cdata, clen, &err)) {
|
||||
+ error_setg(errp, "unable to write config file '%s'", config_path);
|
||||
+ g_free(cdata);
|
||||
+ g_free(basename);
|
||||
+ return 1;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ g_free(basename);
|
||||
+ g_free(cdata);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
bool block_job_should_pause(BlockJob *job);
|
||||
static void pvebackup_run_next_job(void)
|
||||
{
|
||||
@@ -3190,6 +3228,7 @@ static void pvebackup_run_next_job(void)
|
||||
UuidInfo *qmp_backup(const char *backup_file, bool has_format,
|
||||
BackupFormat format,
|
||||
bool has_config_file, const char *config_file,
|
||||
+ bool has_firewall_file, const char *firewall_file,
|
||||
bool has_devlist, const char *devlist,
|
||||
bool has_speed, int64_t speed, Error **errp)
|
||||
{
|
||||
@@ -3342,38 +3381,17 @@ UuidInfo *qmp_backup(const char *backup_file, bool has_format,
|
||||
|
||||
/* add configuration file to archive */
|
||||
if (has_config_file) {
|
||||
- char *cdata = NULL;
|
||||
- gsize clen = 0;
|
||||
- GError *err = NULL;
|
||||
- if (!g_file_get_contents(config_file, &cdata, &clen, &err)) {
|
||||
- error_setg(errp, "unable to read file '%s'", config_file);
|
||||
- goto err;
|
||||
- }
|
||||
-
|
||||
- char *basename = g_path_get_basename(config_file);
|
||||
-
|
||||
- if (format == BACKUP_FORMAT_VMA) {
|
||||
- if (vma_writer_add_config(vmaw, basename, cdata, clen) != 0) {
|
||||
- error_setg(errp, "unable to add config data to vma archive");
|
||||
- g_free(cdata);
|
||||
- g_free(basename);
|
||||
- goto err;
|
||||
- }
|
||||
- } else if (format == BACKUP_FORMAT_DIR) {
|
||||
- char config_path[PATH_MAX];
|
||||
- snprintf(config_path, PATH_MAX, "%s/%s", backup_dir, basename);
|
||||
- if (!g_file_set_contents(config_path, cdata, clen, &err)) {
|
||||
- error_setg(errp, "unable to write config file '%s'", config_path);
|
||||
- g_free(cdata);
|
||||
- g_free(basename);
|
||||
- goto err;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- g_free(basename);
|
||||
- g_free(cdata);
|
||||
+ if(config_to_vma(config_file, format, backup_dir, vmaw, errp) != 0) {
|
||||
+ goto err;
|
||||
+ }
|
||||
}
|
||||
|
||||
+ /* add firewall file to archive */
|
||||
+ if (has_firewall_file) {
|
||||
+ if(config_to_vma(firewall_file, format, backup_dir, vmaw, errp) != 0) {
|
||||
+ goto err;
|
||||
+ }
|
||||
+ }
|
||||
/* initialize global backup_state now */
|
||||
|
||||
backup_state.cancel = false;
|
||||
diff --git a/hmp.c b/hmp.c
|
||||
index aaf0de1642..12f1f46125 100644
|
||||
--- a/hmp.c
|
||||
+++ b/hmp.c
|
||||
@@ -1670,7 +1670,7 @@ void hmp_backup(Monitor *mon, const QDict *qdict)
|
||||
int64_t speed = qdict_get_try_int(qdict, "speed", 0);
|
||||
|
||||
qmp_backup(backup_file, true, dir ? BACKUP_FORMAT_DIR : BACKUP_FORMAT_VMA,
|
||||
- false, NULL, !!devlist,
|
||||
+ false, NULL, false, NULL, !!devlist,
|
||||
devlist, qdict_haskey(qdict, "speed"), speed, &error);
|
||||
|
||||
hmp_handle_error(mon, &error);
|
||||
diff --git a/qapi-schema.json b/qapi-schema.json
|
||||
index 21f822aada..b20020a054 100644
|
||||
--- a/qapi-schema.json
|
||||
+++ b/qapi-schema.json
|
||||
@@ -635,6 +635,7 @@
|
||||
{ 'command': 'backup', 'data': { 'backup-file': 'str',
|
||||
'*format': 'BackupFormat',
|
||||
'*config-file': 'str',
|
||||
+ '*firewall-file': 'str',
|
||||
'*devlist': 'str', '*speed': 'int' },
|
||||
'returns': 'UuidInfo' }
|
||||
|
||||
--
|
||||
2.11.0
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,101 +0,0 @@
|
||||
From c9ec344900b5d2459a70dae88a0e1f309f864775 Mon Sep 17 00:00:00 2001
|
||||
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
|
||||
Date: Thu, 10 Dec 2015 15:14:00 +0100
|
||||
Subject: [PATCH 28/49] savevm-async: migration and bdrv_open update
|
||||
|
||||
---
|
||||
savevm-async.c | 25 ++++++++++++-------------
|
||||
1 file changed, 12 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/savevm-async.c b/savevm-async.c
|
||||
index 9704a412d9..6ac03af9c8 100644
|
||||
--- a/savevm-async.c
|
||||
+++ b/savevm-async.c
|
||||
@@ -154,10 +154,10 @@ static int block_state_close(void *opaque)
|
||||
return bdrv_flush(snap_state.bs);
|
||||
}
|
||||
|
||||
-static int block_state_put_buffer(void *opaque, const uint8_t *buf,
|
||||
- int64_t pos, int size)
|
||||
+static ssize_t block_state_put_buffer(void *opaque, const uint8_t *buf,
|
||||
+ int64_t pos, size_t size)
|
||||
{
|
||||
- int ret;
|
||||
+ ssize_t ret;
|
||||
|
||||
assert(pos == snap_state.bs_pos);
|
||||
|
||||
@@ -201,12 +201,13 @@ static void process_savevm_co(void *opaque)
|
||||
}
|
||||
|
||||
while (snap_state.state == SAVE_STATE_ACTIVE) {
|
||||
- uint64_t pending_size;
|
||||
+ uint64_t pending_size, pend_post, pend_nonpost;
|
||||
|
||||
- pending_size = qemu_savevm_state_pending(snap_state.file, 0);
|
||||
+ qemu_savevm_state_pending(snap_state.file, 0, &pend_nonpost, &pend_post);
|
||||
+ pending_size = pend_post + pend_nonpost;
|
||||
|
||||
if (pending_size) {
|
||||
- ret = qemu_savevm_state_iterate(snap_state.file);
|
||||
+ ret = qemu_savevm_state_iterate(snap_state.file, false);
|
||||
if (ret < 0) {
|
||||
save_snapshot_error("qemu_savevm_state_iterate error %d", ret);
|
||||
break;
|
||||
@@ -217,7 +218,7 @@ static void process_savevm_co(void *opaque)
|
||||
if (store_and_stop())
|
||||
break;
|
||||
DPRINTF("savevm inerate finished\n");
|
||||
- qemu_savevm_state_complete_precopy(snap_state.file);
|
||||
+ qemu_savevm_state_complete_precopy(snap_state.file, false);
|
||||
DPRINTF("save complete\n");
|
||||
save_snapshot_completed();
|
||||
break;
|
||||
@@ -250,7 +251,6 @@ static const QEMUFileOps block_file_ops = {
|
||||
|
||||
void qmp_savevm_start(bool has_statefile, const char *statefile, Error **errp)
|
||||
{
|
||||
- BlockDriver *drv = NULL;
|
||||
Error *local_err = NULL;
|
||||
|
||||
int bdrv_oflags = BDRV_O_RDWR | BDRV_O_RESIZE;
|
||||
@@ -289,7 +289,7 @@ void qmp_savevm_start(bool has_statefile, const char *statefile, Error **errp)
|
||||
QDict *options = NULL;
|
||||
options = qdict_new();
|
||||
qdict_put(options, "driver", qstring_from_str("raw"));
|
||||
- ret = bdrv_open(&snap_state.bs, statefile, NULL, options, bdrv_oflags, drv, &local_err);
|
||||
+ ret = bdrv_open(&snap_state.bs, statefile, NULL, options, bdrv_oflags, &local_err);
|
||||
if (ret < 0) {
|
||||
error_set(errp, ERROR_CLASS_GENERIC_ERROR, "failed to open '%s'", statefile);
|
||||
goto restart;
|
||||
@@ -454,8 +454,8 @@ void qmp_delete_drive_snapshot(const char *device, const char *name,
|
||||
}
|
||||
}
|
||||
|
||||
-static int loadstate_get_buffer(void *opaque, uint8_t *buf, int64_t pos,
|
||||
- int size)
|
||||
+static ssize_t loadstate_get_buffer(void *opaque, uint8_t *buf, int64_t pos,
|
||||
+ size_t size)
|
||||
{
|
||||
BlockDriverState *bs = (BlockDriverState *)opaque;
|
||||
int64_t maxlen = bdrv_getlength(bs);
|
||||
@@ -478,7 +478,6 @@ static const QEMUFileOps loadstate_file_ops = {
|
||||
int load_state_from_blockdev(const char *filename)
|
||||
{
|
||||
BlockDriverState *bs = NULL;
|
||||
- BlockDriver *drv = NULL;
|
||||
Error *local_err = NULL;
|
||||
Error *blocker = NULL;
|
||||
|
||||
@@ -486,7 +485,7 @@ int load_state_from_blockdev(const char *filename)
|
||||
int ret;
|
||||
|
||||
bs = bdrv_new();
|
||||
- ret = bdrv_open(&bs, filename, NULL, NULL, 0, drv, &local_err);
|
||||
+ ret = bdrv_open(&bs, filename, NULL, NULL, 0, &local_err);
|
||||
error_setg(&blocker, "block device is in use by load state");
|
||||
bdrv_op_block_all(bs, blocker);
|
||||
|
||||
--
|
||||
2.11.0
|
||||
|
@ -1,24 +0,0 @@
|
||||
From d79bc8c38a8672f894ad20ffed3529b66560c818 Mon Sep 17 00:00:00 2001
|
||||
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
|
||||
Date: Mon, 8 Feb 2016 08:23:34 +0100
|
||||
Subject: [PATCH 31/49] vma-writer: don't bail out on zero-length files
|
||||
|
||||
---
|
||||
vma-writer.c | 1 -
|
||||
1 file changed, 1 deletion(-)
|
||||
|
||||
diff --git a/vma-writer.c b/vma-writer.c
|
||||
index 0dd668b257..70dcca0771 100644
|
||||
--- a/vma-writer.c
|
||||
+++ b/vma-writer.c
|
||||
@@ -130,7 +130,6 @@ int vma_writer_add_config(VmaWriter *vmaw, const char *name, gpointer data,
|
||||
assert(vmaw->config_count < VMA_MAX_CONFIGS);
|
||||
assert(name);
|
||||
assert(data);
|
||||
- assert(len);
|
||||
|
||||
gchar *basename = g_path_get_basename(name);
|
||||
uint32_t name_ptr = allocate_header_string(vmaw, basename);
|
||||
--
|
||||
2.11.0
|
||||
|
@ -1,42 +0,0 @@
|
||||
From 81e295744d016824a5c756bfc954c63f5a249b5f Mon Sep 17 00:00:00 2001
|
||||
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
|
||||
Date: Tue, 23 Feb 2016 15:48:41 +0100
|
||||
Subject: [PATCH 32/49] vma: better driver guessing for bdrv_open
|
||||
|
||||
Only use 'raw' when the file actually ends with .raw and
|
||||
no protocol has been specified. With protocol pass the
|
||||
BDRV_O_PROTOCOL flag to tell bdrv_fill_options() to take it
|
||||
into account.
|
||||
---
|
||||
vma.c | 15 ++++++++++++++-
|
||||
1 file changed, 14 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/vma.c b/vma.c
|
||||
index c7c05385f6..4903568fb4 100644
|
||||
--- a/vma.c
|
||||
+++ b/vma.c
|
||||
@@ -294,7 +294,20 @@ static int extract_content(int argc, char **argv)
|
||||
}
|
||||
|
||||
BlockDriverState *bs = bdrv_new();
|
||||
- if (errp || bdrv_open(&bs, devfn, NULL, NULL, flags, &errp)) {
|
||||
+
|
||||
+ size_t devlen = strlen(devfn);
|
||||
+ bool protocol = path_has_protocol(devfn);
|
||||
+ QDict *options = NULL;
|
||||
+ if (devlen > 4 && strcmp(devfn+devlen-4, ".raw") == 0 && !protocol) {
|
||||
+ /* explicit raw format */
|
||||
+ options = qdict_new();
|
||||
+ qdict_put(options, "driver", qstring_from_str("raw"));
|
||||
+ } else if (protocol) {
|
||||
+ /* tell bdrv_open to honor the protocol */
|
||||
+ flags |= BDRV_O_PROTOCOL;
|
||||
+ }
|
||||
+
|
||||
+ if (errp || bdrv_open(&bs, devfn, NULL, options, flags, &errp)) {
|
||||
g_error("can't open file %s - %s", devfn,
|
||||
error_get_pretty(errp));
|
||||
}
|
||||
--
|
||||
2.11.0
|
||||
|
@ -1,108 +0,0 @@
|
||||
From 17e81056ca6835c3b800db8b62f093c7f7571d49 Mon Sep 17 00:00:00 2001
|
||||
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
|
||||
Date: Tue, 12 Apr 2016 13:49:44 +0200
|
||||
Subject: [PATCH 34/49] vma: add format option to device mapping
|
||||
|
||||
The BDRV_O_PROTOCOL option breaks non-raw protocol devices,
|
||||
so we instead now allow the format to be explicitly
|
||||
specified from the outside.
|
||||
|
||||
In other words we now too deprecate the automatic guessing
|
||||
of raw formats, just like qemu already does, and have to
|
||||
silence the warnings by passing the drive mapping.
|
||||
---
|
||||
vma.c | 34 +++++++++++++++++++++++++++-------
|
||||
1 file changed, 27 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/vma.c b/vma.c
|
||||
index 4903568fb4..f71e5a5933 100644
|
||||
--- a/vma.c
|
||||
+++ b/vma.c
|
||||
@@ -131,6 +131,7 @@ static int list_content(int argc, char **argv)
|
||||
typedef struct RestoreMap {
|
||||
char *devname;
|
||||
char *path;
|
||||
+ char *format;
|
||||
bool write_zero;
|
||||
} RestoreMap;
|
||||
|
||||
@@ -218,13 +219,24 @@ static int extract_content(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
+ char *format = NULL;
|
||||
+ if (strncmp(line, "format=", sizeof("format=")-1) == 0) {
|
||||
+ format = line + sizeof("format=")-1;
|
||||
+ char *colon = strchr(format, ':');
|
||||
+ if (!colon) {
|
||||
+ g_error("read map failed - found only a format ('%s')", inbuf);
|
||||
+ }
|
||||
+ format = g_strndup(format, colon - format);
|
||||
+ line = colon+1;
|
||||
+ }
|
||||
+
|
||||
const char *path;
|
||||
bool write_zero;
|
||||
if (line[0] == '0' && line[1] == ':') {
|
||||
- path = inbuf + 2;
|
||||
+ path = line + 2;
|
||||
write_zero = false;
|
||||
} else if (line[0] == '1' && line[1] == ':') {
|
||||
- path = inbuf + 2;
|
||||
+ path = line + 2;
|
||||
write_zero = true;
|
||||
} else {
|
||||
g_error("read map failed - parse error ('%s')", inbuf);
|
||||
@@ -240,6 +252,7 @@ static int extract_content(int argc, char **argv)
|
||||
RestoreMap *map = g_new0(RestoreMap, 1);
|
||||
map->devname = g_strdup(devname);
|
||||
map->path = g_strdup(path);
|
||||
+ map->format = format;
|
||||
map->write_zero = write_zero;
|
||||
|
||||
g_hash_table_insert(devmap, map->devname, map);
|
||||
@@ -264,6 +277,7 @@ static int extract_content(int argc, char **argv)
|
||||
g_free(statefn);
|
||||
} else if (di) {
|
||||
char *devfn = NULL;
|
||||
+ const char *format = NULL;
|
||||
int flags = BDRV_O_RDWR;
|
||||
bool write_zero = true;
|
||||
|
||||
@@ -274,6 +288,7 @@ static int extract_content(int argc, char **argv)
|
||||
g_error("no device name mapping for %s", di->devname);
|
||||
}
|
||||
devfn = map->path;
|
||||
+ format = map->format;
|
||||
write_zero = map->write_zero;
|
||||
} else {
|
||||
devfn = g_strdup_printf("%s/tmp-disk-%s.raw",
|
||||
@@ -296,15 +311,20 @@ static int extract_content(int argc, char **argv)
|
||||
BlockDriverState *bs = bdrv_new();
|
||||
|
||||
size_t devlen = strlen(devfn);
|
||||
- bool protocol = path_has_protocol(devfn);
|
||||
QDict *options = NULL;
|
||||
- if (devlen > 4 && strcmp(devfn+devlen-4, ".raw") == 0 && !protocol) {
|
||||
+ if (format) {
|
||||
+ /* explicit format from commandline */
|
||||
+ options = qdict_new();
|
||||
+ qdict_put(options, "driver", qstring_from_str(format));
|
||||
+ } else if ((devlen > 4 && strcmp(devfn+devlen-4, ".raw") == 0) ||
|
||||
+ strncmp(devfn, "/dev/", 5) == 0)
|
||||
+ {
|
||||
+ /* This part is now deprecated for PVE as well (just as qemu
|
||||
+ * deprecated not specifying an explicit raw format, too.
|
||||
+ */
|
||||
/* explicit raw format */
|
||||
options = qdict_new();
|
||||
qdict_put(options, "driver", qstring_from_str("raw"));
|
||||
- } else if (protocol) {
|
||||
- /* tell bdrv_open to honor the protocol */
|
||||
- flags |= BDRV_O_PROTOCOL;
|
||||
}
|
||||
|
||||
if (errp || bdrv_open(&bs, devfn, NULL, options, flags, &errp)) {
|
||||
--
|
||||
2.11.0
|
||||
|
@ -1,87 +0,0 @@
|
||||
From dd70c07d8a666f0046a88626249b2567acdc1c26 Mon Sep 17 00:00:00 2001
|
||||
From: Thomas Lamprecht <t.lamprecht@proxmox.com>
|
||||
Date: Wed, 6 Apr 2016 16:47:54 +0200
|
||||
Subject: [PATCH 36/49] vnc: refactor to QIOChannelSocket
|
||||
|
||||
---
|
||||
ui/vnc-auth-vencrypt.c | 31 ++++++++++++++++---------------
|
||||
1 file changed, 16 insertions(+), 15 deletions(-)
|
||||
|
||||
diff --git a/ui/vnc-auth-vencrypt.c b/ui/vnc-auth-vencrypt.c
|
||||
index de1c1949ba..594ca737a9 100644
|
||||
--- a/ui/vnc-auth-vencrypt.c
|
||||
+++ b/ui/vnc-auth-vencrypt.c
|
||||
@@ -28,27 +28,23 @@
|
||||
#include "vnc.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qemu/main-loop.h"
|
||||
-#include "qemu/sockets.h"
|
||||
+#include "io/channel-socket.h"
|
||||
|
||||
static int protocol_client_auth_plain(VncState *vs, uint8_t *data, size_t len)
|
||||
{
|
||||
- const char *err = NULL;
|
||||
+ Error *err = NULL;
|
||||
char username[256];
|
||||
char passwd[512];
|
||||
|
||||
- char clientip[256];
|
||||
- clientip[0] = 0;
|
||||
- struct sockaddr_in client;
|
||||
- socklen_t addrlen = sizeof(client);
|
||||
- if (getpeername(vs->csock, &client, &addrlen) == 0) {
|
||||
- inet_ntop(client.sin_family, &client.sin_addr,
|
||||
- clientip, sizeof(clientip));
|
||||
+ SocketAddress *clientip = qio_channel_socket_get_remote_address(vs->sioc, &err);
|
||||
+ if (err) {
|
||||
+ goto err;
|
||||
}
|
||||
|
||||
if ((len != (vs->username_len + vs->password_len)) ||
|
||||
(vs->username_len >= (sizeof(username)-1)) ||
|
||||
(vs->password_len >= (sizeof(passwd)-1)) ) {
|
||||
- err = "Got unexpected data length";
|
||||
+ error_setg(&err, "Got unexpected data length");
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -59,26 +55,31 @@ static int protocol_client_auth_plain(VncState *vs, uint8_t *data, size_t len)
|
||||
|
||||
VNC_DEBUG("AUTH PLAIN username: %s pw: %s\n", username, passwd);
|
||||
|
||||
- if (pve_auth_verify(clientip, username, passwd) == 0) {
|
||||
+ if (pve_auth_verify(clientip->u.inet.data->host, username, passwd) == 0) {
|
||||
vnc_write_u32(vs, 0); /* Accept auth completion */
|
||||
start_client_init(vs);
|
||||
+ qapi_free_SocketAddress(clientip);
|
||||
return 0;
|
||||
}
|
||||
|
||||
- err = "Authentication failed";
|
||||
+ error_setg(&err, "Authentication failed");
|
||||
err:
|
||||
if (err) {
|
||||
- VNC_DEBUG("AUTH PLAIN ERROR: %s\n", err);
|
||||
+ const char *err_msg = error_get_pretty(err);
|
||||
+ VNC_DEBUG("AUTH PLAIN ERROR: %s\n", err_msg);
|
||||
vnc_write_u32(vs, 1); /* Reject auth */
|
||||
if (vs->minor >= 8) {
|
||||
- int elen = strlen(err);
|
||||
+ int elen = strlen(err_msg);
|
||||
vnc_write_u32(vs, elen);
|
||||
- vnc_write(vs, err, elen);
|
||||
+ vnc_write(vs, err_msg, elen);
|
||||
}
|
||||
+ error_free(err);
|
||||
}
|
||||
vnc_flush(vs);
|
||||
vnc_client_error(vs);
|
||||
|
||||
+ qapi_free_SocketAddress(clientip);
|
||||
+
|
||||
return 0;
|
||||
|
||||
}
|
||||
--
|
||||
2.11.0
|
||||
|
@ -1,75 +0,0 @@
|
||||
From ccc8208669d45d5442d5f0739ce1e6a158942ea3 Mon Sep 17 00:00:00 2001
|
||||
From: Thomas Lamprecht <t.lamprecht@proxmox.com>
|
||||
Date: Fri, 1 Jul 2016 15:47:29 +0200
|
||||
Subject: [PATCH 37/49] vma: use BlockBackend on extract
|
||||
|
||||
As we else rely on bdrv_close_all() do clean up, which was rewritten
|
||||
in ca9bd24cf1d53775169ba9adc17e265554d1afed and fails on "dangling"
|
||||
BDS pointers, such a pointer exists with *bs.
|
||||
Use the BlockBackend to get our BDS and just unref the BlockBackend
|
||||
when done, it handles the rest for us.
|
||||
|
||||
The other two calls to bdrv_close_all() happen in verify_content()
|
||||
and dump_config(), both do not have a BDS so no need to change here.
|
||||
---
|
||||
vma.c | 13 ++++++++++---
|
||||
1 file changed, 10 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/vma.c b/vma.c
|
||||
index f71e5a5933..ad51090651 100644
|
||||
--- a/vma.c
|
||||
+++ b/vma.c
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "qemu/main-loop.h"
|
||||
#include "qapi/qmp/qstring.h"
|
||||
#include "sysemu/char.h" /* qstring_from_str */
|
||||
+#include "sysemu/block-backend.h"
|
||||
|
||||
static void help(void)
|
||||
{
|
||||
@@ -264,6 +265,8 @@ static int extract_content(int argc, char **argv)
|
||||
int vmstate_fd = -1;
|
||||
guint8 vmstate_stream = 0;
|
||||
|
||||
+ BlockBackend *blk = NULL;
|
||||
+
|
||||
for (i = 1; i < 255; i++) {
|
||||
VmaDeviceInfo *di = vma_reader_get_device_info(vmar, i);
|
||||
if (di && (strcmp(di->devname, "vmstate") == 0)) {
|
||||
@@ -308,8 +311,6 @@ static int extract_content(int argc, char **argv)
|
||||
write_zero = false;
|
||||
}
|
||||
|
||||
- BlockDriverState *bs = bdrv_new();
|
||||
-
|
||||
size_t devlen = strlen(devfn);
|
||||
QDict *options = NULL;
|
||||
if (format) {
|
||||
@@ -327,10 +328,14 @@ static int extract_content(int argc, char **argv)
|
||||
qdict_put(options, "driver", qstring_from_str("raw"));
|
||||
}
|
||||
|
||||
- if (errp || bdrv_open(&bs, devfn, NULL, options, flags, &errp)) {
|
||||
+
|
||||
+ if (errp || !(blk = blk_new_open(devfn, NULL, options, flags, &errp))) {
|
||||
g_error("can't open file %s - %s", devfn,
|
||||
error_get_pretty(errp));
|
||||
}
|
||||
+
|
||||
+ BlockDriverState *bs = blk_bs(blk);
|
||||
+
|
||||
if (vma_reader_register_bs(vmar, i, bs, write_zero, &errp) < 0) {
|
||||
g_error("%s", error_get_pretty(errp));
|
||||
}
|
||||
@@ -363,6 +368,8 @@ static int extract_content(int argc, char **argv)
|
||||
|
||||
vma_reader_destroy(vmar);
|
||||
|
||||
+ blk_unref(blk);
|
||||
+
|
||||
bdrv_close_all();
|
||||
|
||||
return ret;
|
||||
--
|
||||
2.11.0
|
||||
|
@ -1,237 +0,0 @@
|
||||
From b6f11a95c56de227d2c66f4049ace7e01369c920 Mon Sep 17 00:00:00 2001
|
||||
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
|
||||
Date: Fri, 9 Sep 2016 14:51:28 +0200
|
||||
Subject: [PATCH 38/49] vma: byte based write calls
|
||||
|
||||
---
|
||||
vma-reader.c | 42 +++++++++++++++++++++---------------------
|
||||
vma.c | 22 ++++++++++------------
|
||||
vma.h | 2 +-
|
||||
3 files changed, 32 insertions(+), 34 deletions(-)
|
||||
|
||||
diff --git a/vma-reader.c b/vma-reader.c
|
||||
index 78f1de9499..2000889bd3 100644
|
||||
--- a/vma-reader.c
|
||||
+++ b/vma-reader.c
|
||||
@@ -25,7 +25,7 @@
|
||||
static unsigned char zero_vma_block[VMA_BLOCK_SIZE];
|
||||
|
||||
typedef struct VmaRestoreState {
|
||||
- BlockDriverState *bs;
|
||||
+ BlockBackend *target;
|
||||
bool write_zeroes;
|
||||
unsigned long *bitmap;
|
||||
int bitmap_size;
|
||||
@@ -423,12 +423,12 @@ VmaDeviceInfo *vma_reader_get_device_info(VmaReader *vmar, guint8 dev_id)
|
||||
}
|
||||
|
||||
static void allocate_rstate(VmaReader *vmar, guint8 dev_id,
|
||||
- BlockDriverState *bs, bool write_zeroes)
|
||||
+ BlockBackend *target, bool write_zeroes)
|
||||
{
|
||||
assert(vmar);
|
||||
assert(dev_id);
|
||||
|
||||
- vmar->rstate[dev_id].bs = bs;
|
||||
+ vmar->rstate[dev_id].target = target;
|
||||
vmar->rstate[dev_id].write_zeroes = write_zeroes;
|
||||
|
||||
int64_t size = vmar->devinfo[dev_id].size;
|
||||
@@ -443,15 +443,15 @@ static void allocate_rstate(VmaReader *vmar, guint8 dev_id,
|
||||
vmar->cluster_count += size/VMA_CLUSTER_SIZE;
|
||||
}
|
||||
|
||||
-int vma_reader_register_bs(VmaReader *vmar, guint8 dev_id, BlockDriverState *bs,
|
||||
+int vma_reader_register_bs(VmaReader *vmar, guint8 dev_id, BlockBackend *target,
|
||||
bool write_zeroes, Error **errp)
|
||||
{
|
||||
assert(vmar);
|
||||
- assert(bs != NULL);
|
||||
+ assert(target != NULL);
|
||||
assert(dev_id);
|
||||
- assert(vmar->rstate[dev_id].bs == NULL);
|
||||
+ assert(vmar->rstate[dev_id].target == NULL);
|
||||
|
||||
- int64_t size = bdrv_getlength(bs);
|
||||
+ 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
|
||||
@@ -465,7 +465,7 @@ int vma_reader_register_bs(VmaReader *vmar, guint8 dev_id, BlockDriverState *bs,
|
||||
return -1;
|
||||
}
|
||||
|
||||
- allocate_rstate(vmar, dev_id, bs, write_zeroes);
|
||||
+ allocate_rstate(vmar, dev_id, target, write_zeroes);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -507,7 +507,7 @@ static size_t full_write(int fd, void *buf, size_t len)
|
||||
}
|
||||
|
||||
static int restore_write_data(VmaReader *vmar, guint8 dev_id,
|
||||
- BlockDriverState *bs, int vmstate_fd,
|
||||
+ BlockBackend *target, int vmstate_fd,
|
||||
unsigned char *buf, int64_t sector_num,
|
||||
int nb_sectors, Error **errp)
|
||||
{
|
||||
@@ -523,10 +523,10 @@ static int restore_write_data(VmaReader *vmar, guint8 dev_id,
|
||||
}
|
||||
}
|
||||
} else {
|
||||
- int res = bdrv_write(bs, sector_num, buf, nb_sectors);
|
||||
+ int res = blk_pwrite(target, sector_num * BDRV_SECTOR_SIZE, buf, nb_sectors * BDRV_SECTOR_SIZE, 0);
|
||||
if (res < 0) {
|
||||
- error_setg(errp, "bdrv_write to %s failed (%d)",
|
||||
- bdrv_get_device_name(bs), res);
|
||||
+ error_setg(errp, "blk_pwrite to %s failed (%d)",
|
||||
+ bdrv_get_device_name(blk_bs(target)), res);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -556,11 +556,11 @@ static int restore_extent(VmaReader *vmar, unsigned char *buf,
|
||||
}
|
||||
|
||||
VmaRestoreState *rstate = &vmar->rstate[dev_id];
|
||||
- BlockDriverState *bs = NULL;
|
||||
+ BlockBackend *target = NULL;
|
||||
|
||||
if (dev_id != vmar->vmstate_stream) {
|
||||
- bs = rstate->bs;
|
||||
- if (!verify && !bs) {
|
||||
+ target = rstate->target;
|
||||
+ if (!verify && !target) {
|
||||
error_setg(errp, "got wrong dev id %d", dev_id);
|
||||
return -1;
|
||||
}
|
||||
@@ -618,7 +618,7 @@ static int restore_extent(VmaReader *vmar, unsigned char *buf,
|
||||
|
||||
if (!verify) {
|
||||
int nb_sectors = end_sector - sector_num;
|
||||
- if (restore_write_data(vmar, dev_id, bs, vmstate_fd,
|
||||
+ if (restore_write_data(vmar, dev_id, target, vmstate_fd,
|
||||
buf + start, sector_num, nb_sectors,
|
||||
errp) < 0) {
|
||||
return -1;
|
||||
@@ -654,7 +654,7 @@ static int restore_extent(VmaReader *vmar, unsigned char *buf,
|
||||
|
||||
if (!verify) {
|
||||
int nb_sectors = end_sector - sector_num;
|
||||
- if (restore_write_data(vmar, dev_id, bs, vmstate_fd,
|
||||
+ if (restore_write_data(vmar, dev_id, target, vmstate_fd,
|
||||
buf + start, sector_num,
|
||||
nb_sectors, errp) < 0) {
|
||||
return -1;
|
||||
@@ -678,7 +678,7 @@ static int restore_extent(VmaReader *vmar, unsigned char *buf,
|
||||
}
|
||||
|
||||
if (rstate->write_zeroes && !verify) {
|
||||
- if (restore_write_data(vmar, dev_id, bs, vmstate_fd,
|
||||
+ if (restore_write_data(vmar, dev_id, target, vmstate_fd,
|
||||
zero_vma_block, sector_num,
|
||||
nb_sectors, errp) < 0) {
|
||||
return -1;
|
||||
@@ -786,12 +786,12 @@ static int vma_reader_restore_full(VmaReader *vmar, int vmstate_fd,
|
||||
int i;
|
||||
for (i = 1; i < 256; i++) {
|
||||
VmaRestoreState *rstate = &vmar->rstate[i];
|
||||
- if (!rstate->bs) {
|
||||
+ if (!rstate->target) {
|
||||
continue;
|
||||
}
|
||||
|
||||
- if (bdrv_flush(rstate->bs) < 0) {
|
||||
- error_setg(errp, "vma bdrv_flush %s failed",
|
||||
+ if (blk_flush(rstate->target) < 0) {
|
||||
+ error_setg(errp, "vma blk_flush %s failed",
|
||||
vmar->devinfo[i].devname);
|
||||
return -1;
|
||||
}
|
||||
diff --git a/vma.c b/vma.c
|
||||
index ad51090651..aafdc2d7f5 100644
|
||||
--- a/vma.c
|
||||
+++ b/vma.c
|
||||
@@ -334,9 +334,7 @@ static int extract_content(int argc, char **argv)
|
||||
error_get_pretty(errp));
|
||||
}
|
||||
|
||||
- BlockDriverState *bs = blk_bs(blk);
|
||||
-
|
||||
- if (vma_reader_register_bs(vmar, i, bs, write_zero, &errp) < 0) {
|
||||
+ if (vma_reader_register_bs(vmar, i, blk, write_zero, &errp) < 0) {
|
||||
g_error("%s", error_get_pretty(errp));
|
||||
}
|
||||
|
||||
@@ -428,7 +426,7 @@ static int verify_content(int argc, char **argv)
|
||||
}
|
||||
|
||||
typedef struct BackupJob {
|
||||
- BlockDriverState *bs;
|
||||
+ BlockBackend *target;
|
||||
int64_t len;
|
||||
VmaWriter *vmaw;
|
||||
uint8_t dev_id;
|
||||
@@ -457,7 +455,7 @@ static void coroutine_fn backup_run(void *opaque)
|
||||
int64_t start, end;
|
||||
int ret = 0;
|
||||
|
||||
- unsigned char *buf = qemu_blockalign(job->bs, VMA_CLUSTER_SIZE);
|
||||
+ unsigned char *buf = blk_blockalign(job->target, VMA_CLUSTER_SIZE);
|
||||
|
||||
start = 0;
|
||||
end = DIV_ROUND_UP(job->len / BDRV_SECTOR_SIZE,
|
||||
@@ -468,8 +466,8 @@ static void coroutine_fn backup_run(void *opaque)
|
||||
iov.iov_len = VMA_CLUSTER_SIZE;
|
||||
qemu_iovec_init_external(&qiov, &iov, 1);
|
||||
|
||||
- ret = bdrv_co_readv(job->bs, start * BACKUP_SECTORS_PER_CLUSTER,
|
||||
- BACKUP_SECTORS_PER_CLUSTER, &qiov);
|
||||
+ ret = blk_co_preadv(job->target, start * BACKUP_SECTORS_PER_CLUSTER,
|
||||
+ BACKUP_SECTORS_PER_CLUSTER, &qiov, 0);
|
||||
if (ret < 0) {
|
||||
vma_writer_set_error(job->vmaw, "read error", -1);
|
||||
goto out;
|
||||
@@ -564,14 +562,14 @@ static int create_archive(int argc, char **argv)
|
||||
path = extract_devname(path, &devname, devcount++);
|
||||
|
||||
Error *errp = NULL;
|
||||
- BlockDriverState *bs;
|
||||
+ BlockBackend *target;
|
||||
|
||||
- bs = bdrv_open(path, NULL, NULL, 0, &errp);
|
||||
- if (!bs) {
|
||||
+ target = blk_new_open(path, NULL, NULL, 0, &errp);
|
||||
+ if (!target) {
|
||||
unlink(archivename);
|
||||
g_error("bdrv_open '%s' failed - %s", path, error_get_pretty(errp));
|
||||
}
|
||||
- int64_t size = bdrv_getlength(bs);
|
||||
+ int64_t size = blk_getlength(target);
|
||||
int dev_id = vma_writer_register_stream(vmaw, devname, size);
|
||||
if (dev_id <= 0) {
|
||||
unlink(archivename);
|
||||
@@ -580,7 +578,7 @@ static int create_archive(int argc, char **argv)
|
||||
|
||||
BackupJob *job = g_new0(BackupJob, 1);
|
||||
job->len = size;
|
||||
- job->bs = bs;
|
||||
+ job->target = target;
|
||||
job->vmaw = vmaw;
|
||||
job->dev_id = dev_id;
|
||||
|
||||
diff --git a/vma.h b/vma.h
|
||||
index 365ceb2bcb..fa6f4df7e7 100644
|
||||
--- a/vma.h
|
||||
+++ b/vma.h
|
||||
@@ -140,7 +140,7 @@ VmaHeader *vma_reader_get_header(VmaReader *vmar);
|
||||
GList *vma_reader_get_config_data(VmaReader *vmar);
|
||||
VmaDeviceInfo *vma_reader_get_device_info(VmaReader *vmar, guint8 dev_id);
|
||||
int vma_reader_register_bs(VmaReader *vmar, guint8 dev_id,
|
||||
- BlockDriverState *bs, bool write_zeroes,
|
||||
+ BlockBackend *target, bool write_zeroes,
|
||||
Error **errp);
|
||||
int vma_reader_restore(VmaReader *vmar, int vmstate_fd, bool verbose,
|
||||
Error **errp);
|
||||
--
|
||||
2.11.0
|
||||
|
@ -1,43 +0,0 @@
|
||||
From eba97a008e2b0eea7229ba0020b2910f147e545b Mon Sep 17 00:00:00 2001
|
||||
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
|
||||
Date: Mon, 1 Aug 2016 10:52:46 +0200
|
||||
Subject: [PATCH 40/49] enable cache=unsafe for vma extract_content and
|
||||
qmp_savevm_start
|
||||
|
||||
We don't send any flush here, so we need to open with cache=unsafe.
|
||||
|
||||
Signed-off-by: Alexandre Derumier <aderumier@odiso.com>
|
||||
---
|
||||
savevm-async.c | 2 +-
|
||||
vma.c | 2 +-
|
||||
2 files changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/savevm-async.c b/savevm-async.c
|
||||
index 6ac03af9c8..46c1be7887 100644
|
||||
--- a/savevm-async.c
|
||||
+++ b/savevm-async.c
|
||||
@@ -253,7 +253,7 @@ void qmp_savevm_start(bool has_statefile, const char *statefile, Error **errp)
|
||||
{
|
||||
Error *local_err = NULL;
|
||||
|
||||
- int bdrv_oflags = BDRV_O_RDWR | BDRV_O_RESIZE;
|
||||
+ int bdrv_oflags = BDRV_O_RDWR | BDRV_O_RESIZE | BDRV_O_NO_FLUSH;
|
||||
int ret;
|
||||
|
||||
if (snap_state.state != SAVE_STATE_DONE) {
|
||||
diff --git a/vma.c b/vma.c
|
||||
index aafdc2d7f5..4f55799533 100644
|
||||
--- a/vma.c
|
||||
+++ b/vma.c
|
||||
@@ -281,7 +281,7 @@ static int extract_content(int argc, char **argv)
|
||||
} else if (di) {
|
||||
char *devfn = NULL;
|
||||
const char *format = NULL;
|
||||
- int flags = BDRV_O_RDWR;
|
||||
+ int flags = BDRV_O_RDWR | BDRV_O_NO_FLUSH;
|
||||
bool write_zero = true;
|
||||
|
||||
if (readmap) {
|
||||
--
|
||||
2.11.0
|
||||
|
215
debian/patches/pve/0041-savevm-async-updates.patch
vendored
215
debian/patches/pve/0041-savevm-async-updates.patch
vendored
@ -1,215 +0,0 @@
|
||||
From 11d6573ad09a304b79c149c4f98e565f789b128d Mon Sep 17 00:00:00 2001
|
||||
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
|
||||
Date: Fri, 9 Sep 2016 15:21:19 +0200
|
||||
Subject: [PATCH 41/49] savevm-async updates
|
||||
|
||||
---
|
||||
savevm-async.c | 79 +++++++++++++++++++++++++++++-----------------------------
|
||||
1 file changed, 39 insertions(+), 40 deletions(-)
|
||||
|
||||
diff --git a/savevm-async.c b/savevm-async.c
|
||||
index 46c1be7887..2f4766cf6c 100644
|
||||
--- a/savevm-async.c
|
||||
+++ b/savevm-async.c
|
||||
@@ -20,6 +20,8 @@
|
||||
|
||||
/* #define DEBUG_SAVEVM_STATE */
|
||||
|
||||
+#define NOT_DONE 0x7fffffff /* used while emulated sync operation in progress */
|
||||
+
|
||||
#ifdef DEBUG_SAVEVM_STATE
|
||||
#define DPRINTF(fmt, ...) \
|
||||
do { printf("savevm-async: " fmt, ## __VA_ARGS__); } while (0)
|
||||
@@ -38,7 +40,7 @@ enum {
|
||||
|
||||
|
||||
static struct SnapshotState {
|
||||
- BlockDriverState *bs;
|
||||
+ BlockBackend *target;
|
||||
size_t bs_pos;
|
||||
int state;
|
||||
Error *error;
|
||||
@@ -99,17 +101,17 @@ static int save_snapshot_cleanup(void)
|
||||
ret = qemu_fclose(snap_state.file);
|
||||
}
|
||||
|
||||
- if (snap_state.bs) {
|
||||
+ if (snap_state.target) {
|
||||
/* try to truncate, but ignore errors (will fail on block devices).
|
||||
* note: bdrv_read() need whole blocks, so we round up
|
||||
*/
|
||||
size_t size = (snap_state.bs_pos + BDRV_SECTOR_SIZE) & BDRV_SECTOR_MASK;
|
||||
- bdrv_truncate(snap_state.bs, size);
|
||||
- bdrv_op_unblock_all(snap_state.bs, snap_state.blocker);
|
||||
+ blk_truncate(snap_state.target, size);
|
||||
+ blk_op_unblock_all(snap_state.target, snap_state.blocker);
|
||||
error_free(snap_state.blocker);
|
||||
snap_state.blocker = NULL;
|
||||
- bdrv_unref(snap_state.bs);
|
||||
- snap_state.bs = NULL;
|
||||
+ blk_unref(snap_state.target);
|
||||
+ snap_state.target = NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -151,21 +153,22 @@ static void save_snapshot_completed(void)
|
||||
static int block_state_close(void *opaque)
|
||||
{
|
||||
snap_state.file = NULL;
|
||||
- return bdrv_flush(snap_state.bs);
|
||||
+ return blk_flush(snap_state.target);
|
||||
}
|
||||
|
||||
-static ssize_t block_state_put_buffer(void *opaque, const uint8_t *buf,
|
||||
- int64_t pos, size_t size)
|
||||
+static ssize_t block_state_writev_buffer(void *opaque, struct iovec *iov,
|
||||
+ int iovcnt, int64_t pos)
|
||||
{
|
||||
- ssize_t ret;
|
||||
-
|
||||
- assert(pos == snap_state.bs_pos);
|
||||
+ int ret;
|
||||
+ QEMUIOVector qiov;
|
||||
|
||||
- if ((ret = bdrv_pwrite(snap_state.bs, snap_state.bs_pos, buf, size)) > 0) {
|
||||
- snap_state.bs_pos += ret;
|
||||
+ qemu_iovec_init_external(&qiov, iov, iovcnt);
|
||||
+ ret = blk_co_pwritev(snap_state.target, pos, qiov.size, &qiov, 0);
|
||||
+ if (ret < 0) {
|
||||
+ return ret;
|
||||
}
|
||||
-
|
||||
- return ret;
|
||||
+ snap_state.bs_pos += qiov.size;
|
||||
+ return qiov.size;
|
||||
}
|
||||
|
||||
static int store_and_stop(void) {
|
||||
@@ -227,7 +230,7 @@ static void process_savevm_co(void *opaque)
|
||||
/* stop the VM if we get to the end of available space,
|
||||
* or if pending_size is just a few MB
|
||||
*/
|
||||
- maxlen = bdrv_getlength(snap_state.bs) - 30*1024*1024;
|
||||
+ maxlen = blk_getlength(snap_state.target) - 30*1024*1024;
|
||||
if ((pending_size < 100000) ||
|
||||
((snap_state.bs_pos + pending_size) >= maxlen)) {
|
||||
if (store_and_stop())
|
||||
@@ -244,7 +247,7 @@ static void process_savevm_co(void *opaque)
|
||||
}
|
||||
|
||||
static const QEMUFileOps block_file_ops = {
|
||||
- .put_buffer = block_state_put_buffer,
|
||||
+ .writev_buffer = block_state_writev_buffer,
|
||||
.close = block_state_close,
|
||||
};
|
||||
|
||||
@@ -254,7 +257,6 @@ void qmp_savevm_start(bool has_statefile, const char *statefile, Error **errp)
|
||||
Error *local_err = NULL;
|
||||
|
||||
int bdrv_oflags = BDRV_O_RDWR | BDRV_O_RESIZE | BDRV_O_NO_FLUSH;
|
||||
- int ret;
|
||||
|
||||
if (snap_state.state != SAVE_STATE_DONE) {
|
||||
error_set(errp, ERROR_CLASS_GENERIC_ERROR,
|
||||
@@ -284,13 +286,11 @@ void qmp_savevm_start(bool has_statefile, const char *statefile, Error **errp)
|
||||
}
|
||||
|
||||
/* Open the image */
|
||||
- snap_state.bs = bdrv_new();
|
||||
-
|
||||
QDict *options = NULL;
|
||||
options = qdict_new();
|
||||
qdict_put(options, "driver", qstring_from_str("raw"));
|
||||
- ret = bdrv_open(&snap_state.bs, statefile, NULL, options, bdrv_oflags, &local_err);
|
||||
- if (ret < 0) {
|
||||
+ snap_state.target = blk_new_open(statefile, NULL, options, bdrv_oflags, &local_err);
|
||||
+ if (!snap_state.target) {
|
||||
error_set(errp, ERROR_CLASS_GENERIC_ERROR, "failed to open '%s'", statefile);
|
||||
goto restart;
|
||||
}
|
||||
@@ -304,9 +304,9 @@ void qmp_savevm_start(bool has_statefile, const char *statefile, Error **errp)
|
||||
|
||||
|
||||
error_setg(&snap_state.blocker, "block device is in use by savevm");
|
||||
- bdrv_op_block_all(snap_state.bs, snap_state.blocker);
|
||||
+ blk_op_block_all(snap_state.target, snap_state.blocker);
|
||||
|
||||
- Coroutine *co = qemu_coroutine_create(process_savevm_co);
|
||||
+ Coroutine *co = qemu_coroutine_create(process_savevm_co, NULL);
|
||||
qemu_coroutine_enter(co);
|
||||
|
||||
return;
|
||||
@@ -457,8 +457,8 @@ void qmp_delete_drive_snapshot(const char *device, const char *name,
|
||||
static ssize_t loadstate_get_buffer(void *opaque, uint8_t *buf, int64_t pos,
|
||||
size_t size)
|
||||
{
|
||||
- BlockDriverState *bs = (BlockDriverState *)opaque;
|
||||
- int64_t maxlen = bdrv_getlength(bs);
|
||||
+ BlockBackend *be = opaque;
|
||||
+ int64_t maxlen = blk_getlength(be);
|
||||
if (pos > maxlen) {
|
||||
return -EIO;
|
||||
}
|
||||
@@ -468,7 +468,7 @@ static ssize_t loadstate_get_buffer(void *opaque, uint8_t *buf, int64_t pos,
|
||||
if (size == 0) {
|
||||
return 0;
|
||||
}
|
||||
- return bdrv_pread(bs, pos, buf, size);
|
||||
+ return blk_pread(be, pos, buf, size);
|
||||
}
|
||||
|
||||
static const QEMUFileOps loadstate_file_ops = {
|
||||
@@ -477,28 +477,27 @@ static const QEMUFileOps loadstate_file_ops = {
|
||||
|
||||
int load_state_from_blockdev(const char *filename)
|
||||
{
|
||||
- BlockDriverState *bs = NULL;
|
||||
+ BlockBackend *be;
|
||||
Error *local_err = NULL;
|
||||
Error *blocker = NULL;
|
||||
|
||||
QEMUFile *f;
|
||||
- int ret;
|
||||
+ int ret = -EINVAL;
|
||||
|
||||
- bs = bdrv_new();
|
||||
- ret = bdrv_open(&bs, filename, NULL, NULL, 0, &local_err);
|
||||
- error_setg(&blocker, "block device is in use by load state");
|
||||
- bdrv_op_block_all(bs, blocker);
|
||||
+ be = blk_new_open(filename, NULL, NULL, 0, &local_err);
|
||||
|
||||
- if (ret < 0) {
|
||||
+ if (!be) {
|
||||
error_report("Could not open VM state file");
|
||||
goto the_end;
|
||||
}
|
||||
|
||||
+ error_setg(&blocker, "block device is in use by load state");
|
||||
+ blk_op_block_all(be, blocker);
|
||||
+
|
||||
/* restore the VM state */
|
||||
- f = qemu_fopen_ops(bs, &loadstate_file_ops);
|
||||
+ f = qemu_fopen_ops(be, &loadstate_file_ops);
|
||||
if (!f) {
|
||||
error_report("Could not open VM state file");
|
||||
- ret = -EINVAL;
|
||||
goto the_end;
|
||||
}
|
||||
|
||||
@@ -515,10 +514,10 @@ int load_state_from_blockdev(const char *filename)
|
||||
ret = 0;
|
||||
|
||||
the_end:
|
||||
- if (bs) {
|
||||
- bdrv_op_unblock_all(bs, blocker);
|
||||
+ if (be) {
|
||||
+ blk_op_unblock_all(be, blocker);
|
||||
error_free(blocker);
|
||||
- bdrv_unref(bs);
|
||||
+ blk_unref(be);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
--
|
||||
2.11.0
|
||||
|
@ -1,27 +0,0 @@
|
||||
From e74c523db792c8da65faa680ab6898b58b6cb193 Mon Sep 17 00:00:00 2001
|
||||
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
|
||||
Date: Fri, 21 Oct 2016 09:09:26 +0200
|
||||
Subject: [PATCH 43/49] vma: sizes passed to blk_co_preadv should be bytes now
|
||||
|
||||
---
|
||||
vma.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/vma.c b/vma.c
|
||||
index 4f55799533..04915427c8 100644
|
||||
--- a/vma.c
|
||||
+++ b/vma.c
|
||||
@@ -466,8 +466,8 @@ static void coroutine_fn backup_run(void *opaque)
|
||||
iov.iov_len = VMA_CLUSTER_SIZE;
|
||||
qemu_iovec_init_external(&qiov, &iov, 1);
|
||||
|
||||
- ret = blk_co_preadv(job->target, start * BACKUP_SECTORS_PER_CLUSTER,
|
||||
- BACKUP_SECTORS_PER_CLUSTER, &qiov, 0);
|
||||
+ ret = blk_co_preadv(job->target, start * VMA_CLUSTER_SIZE,
|
||||
+ VMA_CLUSTER_SIZE, &qiov, 0);
|
||||
if (ret < 0) {
|
||||
vma_writer_set_error(job->vmaw, "read error", -1);
|
||||
goto out;
|
||||
--
|
||||
2.11.0
|
||||
|
@ -1,52 +0,0 @@
|
||||
From 47d2445ffc83bba6066beb67fa34075d75b5b4c2 Mon Sep 17 00:00:00 2001
|
||||
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
|
||||
Date: Thu, 30 Mar 2017 16:05:34 +0200
|
||||
Subject: [PATCH 48/49] vma: don't use O_DIRECT on pipes
|
||||
|
||||
It puts them in packet mode which potentially discards data.
|
||||
(since kernel 4.5)
|
||||
---
|
||||
vma-writer.c | 10 ++++------
|
||||
1 file changed, 4 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/vma-writer.c b/vma-writer.c
|
||||
index 70dcca0771..9001cbdd2b 100644
|
||||
--- a/vma-writer.c
|
||||
+++ b/vma-writer.c
|
||||
@@ -283,9 +283,8 @@ VmaWriter *vma_writer_create(const char *filename, uuid_t uuid, Error **errp)
|
||||
}
|
||||
vmaw->fd = fileno(vmaw->cmd);
|
||||
|
||||
- /* try to use O_NONBLOCK and O_DIRECT */
|
||||
+ /* try to use O_NONBLOCK */
|
||||
fcntl(vmaw->fd, F_SETFL, fcntl(vmaw->fd, F_GETFL)|O_NONBLOCK);
|
||||
- fcntl(vmaw->fd, F_SETFL, fcntl(vmaw->fd, F_GETFL)|O_DIRECT);
|
||||
|
||||
} else {
|
||||
struct stat st;
|
||||
@@ -293,19 +292,18 @@ VmaWriter *vma_writer_create(const char *filename, uuid_t uuid, Error **errp)
|
||||
const char *tmp_id_str;
|
||||
|
||||
if ((stat(filename, &st) == 0) && S_ISFIFO(st.st_mode)) {
|
||||
- oflags = O_NONBLOCK|O_DIRECT|O_WRONLY;
|
||||
+ oflags = O_NONBLOCK|O_WRONLY;
|
||||
vmaw->fd = qemu_open(filename, oflags, 0644);
|
||||
} else if (strstart(filename, "/dev/fdset/", &tmp_id_str)) {
|
||||
- oflags = O_NONBLOCK|O_DIRECT|O_WRONLY;
|
||||
+ oflags = O_NONBLOCK|O_WRONLY;
|
||||
vmaw->fd = qemu_open(filename, oflags, 0644);
|
||||
} else if (strstart(filename, "/dev/fdname/", &tmp_id_str)) {
|
||||
vmaw->fd = monitor_get_fd(cur_mon, tmp_id_str, errp);
|
||||
if (vmaw->fd < 0) {
|
||||
goto err;
|
||||
}
|
||||
- /* try to use O_NONBLOCK and O_DIRECT */
|
||||
+ /* try to use O_NONBLOCK */
|
||||
fcntl(vmaw->fd, F_SETFL, fcntl(vmaw->fd, F_GETFL)|O_NONBLOCK);
|
||||
- fcntl(vmaw->fd, F_SETFL, fcntl(vmaw->fd, F_GETFL)|O_DIRECT);
|
||||
} else {
|
||||
oflags = O_NONBLOCK|O_DIRECT|O_WRONLY|O_CREAT|O_EXCL;
|
||||
vmaw->fd = qemu_open(filename, oflags, 0644);
|
||||
--
|
||||
2.11.0
|
||||
|
@ -1,25 +0,0 @@
|
||||
From bc3ed255d5a8e9737abe7ba053de2492164f490a Mon Sep 17 00:00:00 2001
|
||||
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
|
||||
Date: Fri, 31 Mar 2017 09:27:58 +0200
|
||||
Subject: [PATCH 49/49] block: zeroinit: request child permissions
|
||||
|
||||
See d7010dfb685
|
||||
---
|
||||
block/zeroinit.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/block/zeroinit.c b/block/zeroinit.c
|
||||
index 0a8c7f9622..a857ec3c62 100644
|
||||
--- a/block/zeroinit.c
|
||||
+++ b/block/zeroinit.c
|
||||
@@ -191,6 +191,7 @@ static BlockDriver bdrv_zeroinit = {
|
||||
.bdrv_file_open = zeroinit_open,
|
||||
.bdrv_close = zeroinit_close,
|
||||
.bdrv_getlength = zeroinit_getlength,
|
||||
+ .bdrv_child_perm = bdrv_filter_default_perms,
|
||||
.bdrv_co_flush_to_disk = zeroinit_co_flush,
|
||||
|
||||
.bdrv_co_pwrite_zeroes = zeroinit_co_pwrite_zeroes,
|
||||
--
|
||||
2.11.0
|
||||
|
74
debian/patches/series
vendored
74
debian/patches/series
vendored
@ -1,53 +1,31 @@
|
||||
pve/0001-fr-ca-keymap-corrections.patch
|
||||
pve/0002-Adjust-network-script-path-to-etc-kvm.patch
|
||||
pve/0003-vnc-altgr-emulation.patch
|
||||
pve/0004-qemu-img-return-success-on-info-without-snapshots.patch
|
||||
pve/0005-use-kvm-by-default.patch
|
||||
pve/0006-virtio-balloon-fix-query.patch
|
||||
pve/0007-set-the-CPU-model-to-kvm64-32-instead-of-qemu64-32.patch
|
||||
pve/0008-qapi-modify-query-machines.patch
|
||||
pve/0009-qapi-modify-spice-query.patch
|
||||
pve/0010-ui-spice-default-to-pve-certs-unless-otherwise-speci.patch
|
||||
pve/0011-introduce-new-vma-archive-format.patch
|
||||
pve/0012-vma-add-verify-command.patch
|
||||
pve/0013-vma-add-config-command-to-dump-the-config.patch
|
||||
pve/0014-backup-modify-job-api.patch
|
||||
pve/0015-backup-add-pve-monitor-commands.patch
|
||||
pve/0016-backup-vma-add-dir-format.patch
|
||||
pve/0017-backup-do-not-return-errors-in-dump-callback.patch
|
||||
pve/0018-backup-vma-correctly-propagate-error.patch
|
||||
pve/0019-backup-vma-remove-async-queue.patch
|
||||
pve/0020-backup-vma-run-flush-inside-coroutine.patch
|
||||
pve/0021-backup-do-not-use-bdrv_drain_all.patch
|
||||
pve/0022-internal-snapshot-async.patch
|
||||
pve/0023-backup-vma-allow-empty-backups.patch
|
||||
pve/0024-qmp-add-get_link_status.patch
|
||||
pve/0025-smm_available-false.patch
|
||||
pve/0026-use-whitespace-between-VERSION-and-PKGVERSION.patch
|
||||
pve/0027-vma-add-firewall.patch
|
||||
pve/0028-savevm-async-migration-and-bdrv_open-update.patch
|
||||
pve/0029-vnc-make-x509-imply-tls-again.patch
|
||||
pve/0030-PVE-VNC-authentication.patch
|
||||
pve/0031-vma-writer-don-t-bail-out-on-zero-length-files.patch
|
||||
pve/0032-vma-better-driver-guessing-for-bdrv_open.patch
|
||||
pve/0033-block-add-the-zeroinit-block-driver-filter.patch
|
||||
pve/0034-vma-add-format-option-to-device-mapping.patch
|
||||
pve/0035-fix-possible-unitialised-return-value.patch
|
||||
pve/0036-vnc-refactor-to-QIOChannelSocket.patch
|
||||
pve/0037-vma-use-BlockBackend-on-extract.patch
|
||||
pve/0038-vma-byte-based-write-calls.patch
|
||||
pve/0039-rbd-disable-rbd_cache_writethrough_until_flush-with-.patch
|
||||
pve/0040-enable-cache-unsafe-for-vma-extract_content-and-qmp_.patch
|
||||
pve/0041-savevm-async-updates.patch
|
||||
pve/0042-qmp_snapshot_drive-add-aiocontext.patch
|
||||
pve/0043-vma-sizes-passed-to-blk_co_preadv-should-be-bytes-no.patch
|
||||
pve/0044-glusterfs-no-default-logfile-if-daemonized.patch
|
||||
pve/0045-qmp_delete_drive_snapshot-add-aiocontext.patch
|
||||
pve/0046-convert-savevm-async-to-threads.patch
|
||||
pve/0047-glusterfs-allow-partial-reads.patch
|
||||
pve/0048-vma-don-t-use-O_DIRECT-on-pipes.patch
|
||||
pve/0049-block-zeroinit-request-child-permissions.patch
|
||||
pve/0050-qemu-img-dd-add-osize-and-read-from-to-stdin-stdout.patch
|
||||
pve/0003-qemu-img-return-success-on-info-without-snapshots.patch
|
||||
pve/0004-use-kvm-by-default.patch
|
||||
pve/0005-virtio-balloon-fix-query.patch
|
||||
pve/0006-set-the-CPU-model-to-kvm64-32-instead-of-qemu64-32.patch
|
||||
pve/0007-qapi-modify-query-machines.patch
|
||||
pve/0008-qapi-modify-spice-query.patch
|
||||
pve/0009-ui-spice-default-to-pve-certs-unless-otherwise-speci.patch
|
||||
pve/0010-internal-snapshot-async.patch
|
||||
pve/0011-convert-savevm-async-to-threads.patch
|
||||
pve/0012-qmp-add-get_link_status.patch
|
||||
pve/0013-smm_available-false.patch
|
||||
pve/0014-use-whitespace-between-VERSION-and-PKGVERSION.patch
|
||||
pve/0015-vnc-altgr-emulation.patch
|
||||
pve/0016-vnc-make-x509-imply-tls-again.patch
|
||||
pve/0017-vnc-PVE-VNC-authentication.patch
|
||||
pve/0018-migrate-fix-possible-unitialised-return-value.patch
|
||||
pve/0019-block-rbd-disable-rbd_cache_writethrough_until_flush.patch
|
||||
pve/0020-block-snapshot-qmp_snapshot_drive-add-aiocontext.patch
|
||||
pve/0021-block-snapshot-qmp_delete_drive_snapshot-add-aiocont.patch
|
||||
pve/0022-glusterfs-no-default-logfile-if-daemonized.patch
|
||||
pve/0023-glusterfs-allow-partial-reads.patch
|
||||
pve/0024-block-add-the-zeroinit-block-driver-filter.patch
|
||||
pve/0025-qemu-img-dd-add-osize-and-read-from-to-stdin-stdout.patch
|
||||
pve/0026-backup-modify-job-api.patch
|
||||
pve/0027-backup-introduce-vma-archive-format.patch
|
||||
pve/0028-adding-old-vma-files.patch
|
||||
extra/0001-Revert-target-i386-disable-LINT0-after-reset.patch
|
||||
extra/0002-qemu-img-wait-for-convert-coroutines-to-complete.patch
|
||||
extra/0003-block-Do-not-unref-bs-file-on-error-in-BD-s-open.patch
|
||||
|
Loading…
Reference in New Issue
Block a user