]> git.proxmox.com Git - pve-qemu-kvm.git/blob - debian/patches/pve/0041-savevm-async-updates.patch
942073c6e92afe2738f813ee30731c6a770154c9
[pve-qemu-kvm.git] / debian / patches / pve / 0041-savevm-async-updates.patch
1 From 8ba1bc13200b72a287554224b5aeb8cbf1bba156 Mon Sep 17 00:00:00 2001
2 From: Wolfgang Bumiller <w.bumiller@proxmox.com>
3 Date: Fri, 9 Sep 2016 15:21:19 +0200
4 Subject: [PATCH 41/41] savevm-async updates
5
6 ---
7 savevm-async.c | 99 +++++++++++++++++++++++++++++++++++++---------------------
8 1 file changed, 63 insertions(+), 36 deletions(-)
9
10 diff --git a/savevm-async.c b/savevm-async.c
11 index 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 --
235 2.1.4
236