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
7 savevm-async.c | 99 +++++++++++++++++++++++++++++++++++++---------------------
8 1 file changed, 63 insertions(+), 36 deletions(-)
10 diff --git a/savevm-async.c b/savevm-async.c
11 index 76cd8fa..fddb18c 100644
16 /* #define DEBUG_SAVEVM_STATE */
18 +#define NOT_DONE 0x7fffffff /* used while emulated sync operation in progress */
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 {
26 static struct SnapshotState {
27 - BlockDriverState *bs;
28 + BlockBackend *target;
32 @@ -99,17 +101,17 @@ static int save_snapshot_cleanup(void)
33 ret = qemu_fclose(snap_state.file);
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
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;
55 @@ -151,21 +153,49 @@ static void save_snapshot_completed(void)
56 static int block_state_close(void *opaque)
58 snap_state.file = NULL;
59 - return bdrv_flush(snap_state.bs);
60 + return blk_flush(snap_state.target);
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 {
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,
77 +static ssize_t block_state_writev_buffer(void *opaque, struct iovec *iov,
78 + int iovcnt, int64_t pos)
81 + AioContext *aio_context;
86 + qemu_iovec_init_external(&qiov, iov, iovcnt);
94 - assert(pos == snap_state.bs_pos);
95 + co = qemu_coroutine_create(&block_state_write_entry, &rwco);
96 + qemu_coroutine_enter(co);
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);
106 + if (rwco.ret < 0) {
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
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)
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,
131 @@ -254,7 +284,6 @@ void qmp_savevm_start(bool has_statefile, const char *statefile, Error **errp)
132 Error *local_err = NULL;
134 int bdrv_oflags = BDRV_O_RDWR | BDRV_O_NO_FLUSH;
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)
143 - snap_state.bs = bdrv_new();
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);
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);
155 @@ -304,9 +331,9 @@ void qmp_savevm_start(bool has_statefile, const char *statefile, Error **errp)
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);
162 - Coroutine *co = qemu_coroutine_create(process_savevm_co);
163 + Coroutine *co = qemu_coroutine_create(process_savevm_co, NULL);
164 qemu_coroutine_enter(co);
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,
171 - BlockDriverState *bs = (BlockDriverState *)opaque;
172 - int64_t maxlen = bdrv_getlength(bs);
173 + BlockBackend *be = opaque;
174 + int64_t maxlen = blk_getlength(be);
178 @@ -468,7 +495,7 @@ static ssize_t loadstate_get_buffer(void *opaque, uint8_t *buf, int64_t pos,
182 - return bdrv_pread(bs, pos, buf, size);
183 + return blk_pread(be, pos, buf, size);
186 static const QEMUFileOps loadstate_file_ops = {
187 @@ -477,25 +504,25 @@ static const QEMUFileOps loadstate_file_ops = {
189 int load_state_from_blockdev(const char *filename)
191 - BlockDriverState *bs = NULL;
193 Error *local_err = NULL;
194 Error *blocker = NULL;
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);
207 error_report("Could not open VM state file");
211 + error_setg(&blocker, "block device is in use by load state");
212 + blk_op_block_all(be, blocker);
214 /* restore the VM state */
215 - f = qemu_fopen_ops(bs, &loadstate_file_ops);
216 + f = qemu_fopen_ops(be, &loadstate_file_ops);
218 error_report("Could not open VM state file");
220 @@ -516,10 +543,10 @@ int load_state_from_blockdev(const char *filename)
225 - bdrv_op_unblock_all(bs, blocker);
227 + blk_op_unblock_all(be, blocker);