rebased pve patches

master
Wolfgang Bumiller 2017-08-07 09:10:07 +02:00
parent 3c6facff3f
commit 67af0fa481
53 changed files with 2877 additions and 4319 deletions

View File

@ -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 +++++++++

View File

@ -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 +++--

View File

@ -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 ++-

View File

@ -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 ++--

View File

@ -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.

View File

@ -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 ++--

View File

@ -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
---

View File

@ -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.
---

View File

@ -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
---

View File

@ -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;
+ }
+
+ 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;
+}

View File

@ -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);

View File

@ -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'} }
##

View File

@ -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

View File

@ -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>
---

View File

@ -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

View File

@ -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

View File

@ -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()

View File

@ -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

View File

@ -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 +++++++++++++++++++++++++-

View File

@ -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

View File

@ -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 ++---

View File

@ -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

View File

@ -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 {

View File

@ -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

View File

@ -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 +-

View File

@ -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

View File

@ -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>
---

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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;
}

View File

@ -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 +++++++++++----

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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

View 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

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
View File

@ -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