]> git.proxmox.com Git - pve-qemu.git/blob - debian/patches/pve/0017-PVE-add-IOChannel-implementation-for-savevm-async.patch
bump version to 8.0.2-1
[pve-qemu.git] / debian / patches / pve / 0017-PVE-add-IOChannel-implementation-for-savevm-async.patch
1 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 From: Fiona Ebner <f.ebner@proxmox.com>
3 Date: Thu, 13 Oct 2022 11:33:50 +0200
4 Subject: [PATCH] PVE: add IOChannel implementation for savevm-async
5
6 based on migration/channel-block.c and the implementation that was
7 present in migration/savevm-async.c before QEMU 7.1.
8
9 Passes along read/write requests to the given BlockBackend, while
10 ensuring that a read request going beyond the end results in a
11 graceful short read.
12
13 Additionally, allows tracking the current position from the outside
14 (intended to be used for progress tracking).
15
16 Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
17 ---
18 migration/channel-savevm-async.c | 183 +++++++++++++++++++++++++++++++
19 migration/channel-savevm-async.h | 51 +++++++++
20 migration/meson.build | 1 +
21 3 files changed, 235 insertions(+)
22 create mode 100644 migration/channel-savevm-async.c
23 create mode 100644 migration/channel-savevm-async.h
24
25 diff --git a/migration/channel-savevm-async.c b/migration/channel-savevm-async.c
26 new file mode 100644
27 index 0000000000..aab081ce07
28 --- /dev/null
29 +++ b/migration/channel-savevm-async.c
30 @@ -0,0 +1,183 @@
31 +/*
32 + * QIO Channel implementation to be used by savevm-async QMP calls
33 + */
34 +#include "qemu/osdep.h"
35 +#include "migration/channel-savevm-async.h"
36 +#include "qapi/error.h"
37 +#include "sysemu/block-backend.h"
38 +#include "trace.h"
39 +
40 +QIOChannelSavevmAsync *
41 +qio_channel_savevm_async_new(BlockBackend *be, size_t *bs_pos)
42 +{
43 + QIOChannelSavevmAsync *ioc;
44 +
45 + ioc = QIO_CHANNEL_SAVEVM_ASYNC(object_new(TYPE_QIO_CHANNEL_SAVEVM_ASYNC));
46 +
47 + bdrv_ref(blk_bs(be));
48 + ioc->be = be;
49 + ioc->bs_pos = bs_pos;
50 +
51 + return ioc;
52 +}
53 +
54 +
55 +static void
56 +qio_channel_savevm_async_finalize(Object *obj)
57 +{
58 + QIOChannelSavevmAsync *ioc = QIO_CHANNEL_SAVEVM_ASYNC(obj);
59 +
60 + if (ioc->be) {
61 + bdrv_unref(blk_bs(ioc->be));
62 + ioc->be = NULL;
63 + }
64 + ioc->bs_pos = NULL;
65 +}
66 +
67 +
68 +static ssize_t
69 +qio_channel_savevm_async_readv(QIOChannel *ioc,
70 + const struct iovec *iov,
71 + size_t niov,
72 + int **fds,
73 + size_t *nfds,
74 + int flags,
75 + Error **errp)
76 +{
77 + QIOChannelSavevmAsync *saioc = QIO_CHANNEL_SAVEVM_ASYNC(ioc);
78 + BlockBackend *be = saioc->be;
79 + int64_t maxlen = blk_getlength(be);
80 + QEMUIOVector qiov;
81 + size_t size;
82 + int ret;
83 +
84 + qemu_iovec_init_external(&qiov, (struct iovec *)iov, niov);
85 +
86 + if (*saioc->bs_pos >= maxlen) {
87 + error_setg(errp, "cannot read beyond maxlen");
88 + return -1;
89 + }
90 +
91 + if (maxlen - *saioc->bs_pos < qiov.size) {
92 + size = maxlen - *saioc->bs_pos;
93 + } else {
94 + size = qiov.size;
95 + }
96 +
97 + // returns 0 on success
98 + ret = blk_preadv(be, *saioc->bs_pos, size, &qiov, 0);
99 + if (ret < 0) {
100 + error_setg_errno(errp, -ret, "blk_preadv failed");
101 + return -1;
102 + }
103 +
104 + *saioc->bs_pos += size;
105 + return size;
106 +}
107 +
108 +
109 +static ssize_t
110 +qio_channel_savevm_async_writev(QIOChannel *ioc,
111 + const struct iovec *iov,
112 + size_t niov,
113 + int *fds,
114 + size_t nfds,
115 + int flags,
116 + Error **errp)
117 +{
118 + QIOChannelSavevmAsync *saioc = QIO_CHANNEL_SAVEVM_ASYNC(ioc);
119 + BlockBackend *be = saioc->be;
120 + QEMUIOVector qiov;
121 + int ret;
122 +
123 + qemu_iovec_init_external(&qiov, (struct iovec *)iov, niov);
124 +
125 + if (qemu_in_coroutine()) {
126 + ret = blk_co_pwritev(be, *saioc->bs_pos, qiov.size, &qiov, 0);
127 + aio_wait_kick();
128 + } else {
129 + ret = blk_pwritev(be, *saioc->bs_pos, qiov.size, &qiov, 0);
130 + }
131 +
132 + if (ret < 0) {
133 + error_setg_errno(errp, -ret, "blk(_co)_pwritev failed");
134 + return -1;
135 + }
136 +
137 + *saioc->bs_pos += qiov.size;
138 + return qiov.size;
139 +}
140 +
141 +
142 +static int
143 +qio_channel_savevm_async_set_blocking(QIOChannel *ioc,
144 + bool enabled,
145 + Error **errp)
146 +{
147 + if (!enabled) {
148 + error_setg(errp, "Non-blocking mode not supported for savevm-async");
149 + return -1;
150 + }
151 + return 0;
152 +}
153 +
154 +
155 +static int
156 +qio_channel_savevm_async_close(QIOChannel *ioc,
157 + Error **errp)
158 +{
159 + QIOChannelSavevmAsync *saioc = QIO_CHANNEL_SAVEVM_ASYNC(ioc);
160 + int rv = bdrv_flush(blk_bs(saioc->be));
161 +
162 + if (rv < 0) {
163 + error_setg_errno(errp, -rv, "Unable to flush VMState");
164 + return -1;
165 + }
166 +
167 + bdrv_unref(blk_bs(saioc->be));
168 + saioc->be = NULL;
169 + saioc->bs_pos = NULL;
170 +
171 + return 0;
172 +}
173 +
174 +
175 +static void
176 +qio_channel_savevm_async_set_aio_fd_handler(QIOChannel *ioc,
177 + AioContext *ctx,
178 + IOHandler *io_read,
179 + IOHandler *io_write,
180 + void *opaque)
181 +{
182 + // if channel-block starts doing something, check if this needs adaptation
183 +}
184 +
185 +
186 +static void
187 +qio_channel_savevm_async_class_init(ObjectClass *klass,
188 + void *class_data G_GNUC_UNUSED)
189 +{
190 + QIOChannelClass *ioc_klass = QIO_CHANNEL_CLASS(klass);
191 +
192 + ioc_klass->io_writev = qio_channel_savevm_async_writev;
193 + ioc_klass->io_readv = qio_channel_savevm_async_readv;
194 + ioc_klass->io_set_blocking = qio_channel_savevm_async_set_blocking;
195 + ioc_klass->io_close = qio_channel_savevm_async_close;
196 + ioc_klass->io_set_aio_fd_handler = qio_channel_savevm_async_set_aio_fd_handler;
197 +}
198 +
199 +static const TypeInfo qio_channel_savevm_async_info = {
200 + .parent = TYPE_QIO_CHANNEL,
201 + .name = TYPE_QIO_CHANNEL_SAVEVM_ASYNC,
202 + .instance_size = sizeof(QIOChannelSavevmAsync),
203 + .instance_finalize = qio_channel_savevm_async_finalize,
204 + .class_init = qio_channel_savevm_async_class_init,
205 +};
206 +
207 +static void
208 +qio_channel_savevm_async_register_types(void)
209 +{
210 + type_register_static(&qio_channel_savevm_async_info);
211 +}
212 +
213 +type_init(qio_channel_savevm_async_register_types);
214 diff --git a/migration/channel-savevm-async.h b/migration/channel-savevm-async.h
215 new file mode 100644
216 index 0000000000..17ae2cb261
217 --- /dev/null
218 +++ b/migration/channel-savevm-async.h
219 @@ -0,0 +1,51 @@
220 +/*
221 + * QEMU I/O channels driver for savevm-async.c
222 + *
223 + * Copyright (c) 2022 Proxmox Server Solutions
224 + *
225 + * Authors:
226 + * Fiona Ebner (f.ebner@proxmox.com)
227 + *
228 + * This work is licensed under the terms of the GNU GPL, version 2 or later.
229 + * See the COPYING file in the top-level directory.
230 + */
231 +
232 +#ifndef QIO_CHANNEL_SAVEVM_ASYNC_H
233 +#define QIO_CHANNEL_SAVEVM_ASYNC_H
234 +
235 +#include "io/channel.h"
236 +#include "qom/object.h"
237 +
238 +#define TYPE_QIO_CHANNEL_SAVEVM_ASYNC "qio-channel-savevm-async"
239 +OBJECT_DECLARE_SIMPLE_TYPE(QIOChannelSavevmAsync, QIO_CHANNEL_SAVEVM_ASYNC)
240 +
241 +
242 +/**
243 + * QIOChannelSavevmAsync:
244 + *
245 + * The QIOChannelBlock object provides a channel implementation that is able to
246 + * perform I/O on any BlockBackend whose BlockDriverState directly contains a
247 + * VMState (as opposed to indirectly, like qcow2). It allows tracking the
248 + * current position from the outside.
249 + */
250 +struct QIOChannelSavevmAsync {
251 + QIOChannel parent;
252 + BlockBackend *be;
253 + size_t *bs_pos;
254 +};
255 +
256 +
257 +/**
258 + * qio_channel_savevm_async_new:
259 + * @be: the block backend
260 + * @bs_pos: used to keep track of the IOChannels current position
261 + *
262 + * Create a new IO channel object that can perform I/O on a BlockBackend object
263 + * whose BlockDriverState directly contains a VMState.
264 + *
265 + * Returns: the new channel object
266 + */
267 +QIOChannelSavevmAsync *
268 +qio_channel_savevm_async_new(BlockBackend *be, size_t *bs_pos);
269 +
270 +#endif /* QIO_CHANNEL_SAVEVM_ASYNC_H */
271 diff --git a/migration/meson.build b/migration/meson.build
272 index 0d1bb9f96e..8a142fc7a9 100644
273 --- a/migration/meson.build
274 +++ b/migration/meson.build
275 @@ -13,6 +13,7 @@ softmmu_ss.add(files(
276 'block-dirty-bitmap.c',
277 'channel.c',
278 'channel-block.c',
279 + 'channel-savevm-async.c',
280 'colo-failover.c',
281 'colo.c',
282 'exec.c',