]>
Commit | Line | Data |
---|---|---|
68a30562 WB |
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 |