]> git.proxmox.com Git - pve-qemu-kvm.git/blame - debian/patches/pve/0041-savevm-async-updates.patch
add vma backup fix
[pve-qemu-kvm.git] / debian / patches / pve / 0041-savevm-async-updates.patch
CommitLineData
68a30562
WB
1From 8ba1bc13200b72a287554224b5aeb8cbf1bba156 Mon Sep 17 00:00:00 2001
2From: Wolfgang Bumiller <w.bumiller@proxmox.com>
3Date: Fri, 9 Sep 2016 15:21:19 +0200
4Subject: [PATCH 41/41] savevm-async updates
5
6---
7 savevm-async.c | 99 +++++++++++++++++++++++++++++++++++++---------------------
8 1 file changed, 63 insertions(+), 36 deletions(-)
9
10diff --git a/savevm-async.c b/savevm-async.c
11index 76cd8fa..fddb18c 100644
12--- a/savevm-async.c
13+++ b/savevm-async.c
14@@ -20,6 +20,8 @@
15
16 /* #define DEBUG_SAVEVM_STATE */
17
18+#define NOT_DONE 0x7fffffff /* used while emulated sync operation in progress */
19+
20 #ifdef DEBUG_SAVEVM_STATE
21 #define DPRINTF(fmt, ...) \
22 do { printf("savevm-async: " fmt, ## __VA_ARGS__); } while (0)
23@@ -38,7 +40,7 @@ enum {
24
25
26 static struct SnapshotState {
27- BlockDriverState *bs;
28+ BlockBackend *target;
29 size_t bs_pos;
30 int state;
31 Error *error;
32@@ -99,17 +101,17 @@ static int save_snapshot_cleanup(void)
33 ret = qemu_fclose(snap_state.file);
34 }
35
36- if (snap_state.bs) {
37+ if (snap_state.target) {
38 /* try to truncate, but ignore errors (will fail on block devices).
39 * note: bdrv_read() need whole blocks, so we round up
40 */
41 size_t size = (snap_state.bs_pos + BDRV_SECTOR_SIZE) & BDRV_SECTOR_MASK;
42- bdrv_truncate(snap_state.bs, size);
43- bdrv_op_unblock_all(snap_state.bs, snap_state.blocker);
44+ blk_truncate(snap_state.target, size);
45+ blk_op_unblock_all(snap_state.target, snap_state.blocker);
46 error_free(snap_state.blocker);
47 snap_state.blocker = NULL;
48- bdrv_unref(snap_state.bs);
49- snap_state.bs = NULL;
50+ blk_unref(snap_state.target);
51+ snap_state.target = NULL;
52 }
53
54 return ret;
55@@ -151,21 +153,49 @@ static void save_snapshot_completed(void)
56 static int block_state_close(void *opaque)
57 {
58 snap_state.file = NULL;
59- return bdrv_flush(snap_state.bs);
60+ return blk_flush(snap_state.target);
61 }
62
63-static ssize_t block_state_put_buffer(void *opaque, const uint8_t *buf,
64- int64_t pos, size_t size)
65+typedef struct BlkRwCo {
66+ int64_t offset;
67+ QEMUIOVector *qiov;
68+ int ret;
69+} BlkRwCo;
70+
71+static void block_state_write_entry(void *opaque) {
72+ BlkRwCo *rwco = opaque;
73+ rwco->ret = blk_co_pwritev(snap_state.target, rwco->offset, rwco->qiov->size,
74+ rwco->qiov, 0);
75+}
76+
77+static ssize_t block_state_writev_buffer(void *opaque, struct iovec *iov,
78+ int iovcnt, int64_t pos)
79 {
80- ssize_t ret;
81+ AioContext *aio_context;
82+ QEMUIOVector qiov;
83+ Coroutine *co;
84+ BlkRwCo rwco;
85+
86+ qemu_iovec_init_external(&qiov, iov, iovcnt);
87+
88+ rwco = (BlkRwCo) {
89+ .offset = pos,
90+ .qiov = &qiov,
91+ .ret = NOT_DONE,
92+ };
93
94- assert(pos == snap_state.bs_pos);
95+ co = qemu_coroutine_create(&block_state_write_entry, &rwco);
96+ qemu_coroutine_enter(co);
97
98- if ((ret = bdrv_pwrite(snap_state.bs, snap_state.bs_pos, buf, size)) > 0) {
99- snap_state.bs_pos += ret;
100+ aio_context = blk_get_aio_context(snap_state.target);
101+ while (rwco.ret == NOT_DONE) {
102+ aio_poll(aio_context, true);
103 }
104
105- return ret;
106+ if (rwco.ret < 0) {
107+ return rwco.ret;
108+ }
109+ return qiov.size;
110 }
111
112 static int store_and_stop(void) {
113@@ -227,7 +257,7 @@ static void process_savevm_co(void *opaque)
114 /* stop the VM if we get to the end of available space,
115 * or if pending_size is just a few MB
116 */
117- maxlen = bdrv_getlength(snap_state.bs) - 30*1024*1024;
118+ maxlen = blk_getlength(snap_state.target) - 30*1024*1024;
119 if ((pending_size < 100000) ||
120 ((snap_state.bs_pos + pending_size) >= maxlen)) {
121 if (store_and_stop())
122@@ -244,7 +274,7 @@ static void process_savevm_co(void *opaque)
123 }
124
125 static const QEMUFileOps block_file_ops = {
126- .put_buffer = block_state_put_buffer,
127+ .writev_buffer = block_state_writev_buffer,
128 .close = block_state_close,
129 };
130
131@@ -254,7 +284,6 @@ void qmp_savevm_start(bool has_statefile, const char *statefile, Error **errp)
132 Error *local_err = NULL;
133
134 int bdrv_oflags = BDRV_O_RDWR | BDRV_O_NO_FLUSH;
135- int ret;
136
137 if (snap_state.state != SAVE_STATE_DONE) {
138 error_set(errp, ERROR_CLASS_GENERIC_ERROR,
139@@ -284,13 +313,11 @@ void qmp_savevm_start(bool has_statefile, const char *statefile, Error **errp)
140 }
141
142 /* Open the image */
143- snap_state.bs = bdrv_new();
144-
145 QDict *options = NULL;
146 options = qdict_new();
147 qdict_put(options, "driver", qstring_from_str("raw"));
148- ret = bdrv_open(&snap_state.bs, statefile, NULL, options, bdrv_oflags, &local_err);
149- if (ret < 0) {
150+ snap_state.target = blk_new_open(statefile, NULL, options, bdrv_oflags, &local_err);
151+ if (!snap_state.target) {
152 error_set(errp, ERROR_CLASS_GENERIC_ERROR, "failed to open '%s'", statefile);
153 goto restart;
154 }
155@@ -304,9 +331,9 @@ void qmp_savevm_start(bool has_statefile, const char *statefile, Error **errp)
156
157
158 error_setg(&snap_state.blocker, "block device is in use by savevm");
159- bdrv_op_block_all(snap_state.bs, snap_state.blocker);
160+ blk_op_block_all(snap_state.target, snap_state.blocker);
161
162- Coroutine *co = qemu_coroutine_create(process_savevm_co);
163+ Coroutine *co = qemu_coroutine_create(process_savevm_co, NULL);
164 qemu_coroutine_enter(co);
165
166 return;
167@@ -457,8 +484,8 @@ void qmp_delete_drive_snapshot(const char *device, const char *name,
168 static ssize_t loadstate_get_buffer(void *opaque, uint8_t *buf, int64_t pos,
169 size_t size)
170 {
171- BlockDriverState *bs = (BlockDriverState *)opaque;
172- int64_t maxlen = bdrv_getlength(bs);
173+ BlockBackend *be = opaque;
174+ int64_t maxlen = blk_getlength(be);
175 if (pos > maxlen) {
176 return -EIO;
177 }
178@@ -468,7 +495,7 @@ static ssize_t loadstate_get_buffer(void *opaque, uint8_t *buf, int64_t pos,
179 if (size == 0) {
180 return 0;
181 }
182- return bdrv_pread(bs, pos, buf, size);
183+ return blk_pread(be, pos, buf, size);
184 }
185
186 static const QEMUFileOps loadstate_file_ops = {
187@@ -477,25 +504,25 @@ static const QEMUFileOps loadstate_file_ops = {
188
189 int load_state_from_blockdev(const char *filename)
190 {
191- BlockDriverState *bs = NULL;
192+ BlockBackend *be;
193 Error *local_err = NULL;
194 Error *blocker = NULL;
195
196 QEMUFile *f;
197 int ret;
198
199- bs = bdrv_new();
200- ret = bdrv_open(&bs, filename, NULL, NULL, 0, &local_err);
201- error_setg(&blocker, "block device is in use by load state");
202- bdrv_op_block_all(bs, blocker);
203+ be = blk_new_open(filename, NULL, NULL, 0, &local_err);
204
205- if (ret < 0) {
206+ if (!be) {
207 error_report("Could not open VM state file");
208 goto the_end;
209 }
210
211+ error_setg(&blocker, "block device is in use by load state");
212+ blk_op_block_all(be, blocker);
213+
214 /* restore the VM state */
215- f = qemu_fopen_ops(bs, &loadstate_file_ops);
216+ f = qemu_fopen_ops(be, &loadstate_file_ops);
217 if (!f) {
218 error_report("Could not open VM state file");
219 ret = -EINVAL;
220@@ -516,10 +543,10 @@ int load_state_from_blockdev(const char *filename)
221 ret = 0;
222
223 the_end:
224- if (bs) {
225- bdrv_op_unblock_all(bs, blocker);
226+ if (be) {
227+ blk_op_unblock_all(be, blocker);
228 error_free(blocker);
229- bdrv_unref(bs);
230+ blk_unref(be);
231 }
232 return ret;
233 }
234--
2352.1.4
236