]> git.proxmox.com Git - pve-qemu.git/blame - debian/patches/pve/0016-PVE-add-IOChannel-implementation-for-savevm-async.patch
buildsys: use QEMU's keycodemapdb again
[pve-qemu.git] / debian / patches / pve / 0016-PVE-add-IOChannel-implementation-for-savevm-async.patch
CommitLineData
5b15e2ec
FE
1From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2From: Fiona Ebner <f.ebner@proxmox.com>
3Date: Thu, 13 Oct 2022 11:33:50 +0200
4Subject: [PATCH] PVE: add IOChannel implementation for savevm-async
5
6based on migration/channel-block.c and the implementation that was
7present in migration/savevm-async.c before QEMU 7.1.
8
9Passes along read/write requests to the given BlockBackend, while
10ensuring that a read request going beyond the end results in a
11graceful short read.
12
13Additionally, allows tracking the current position from the outside
14(intended to be used for progress tracking).
15
16Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
17---
bf251437 18 migration/channel-savevm-async.c | 183 +++++++++++++++++++++++++++++++
5b15e2ec
FE
19 migration/channel-savevm-async.h | 51 +++++++++
20 migration/meson.build | 1 +
bf251437 21 3 files changed, 235 insertions(+)
5b15e2ec
FE
22 create mode 100644 migration/channel-savevm-async.c
23 create mode 100644 migration/channel-savevm-async.h
24
25diff --git a/migration/channel-savevm-async.c b/migration/channel-savevm-async.c
26new file mode 100644
bf251437 27index 0000000000..aab081ce07
5b15e2ec
FE
28--- /dev/null
29+++ b/migration/channel-savevm-async.c
bf251437 30@@ -0,0 +1,183 @@
5b15e2ec
FE
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,
bf251437 74+ int flags,
5b15e2ec
FE
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) {
0af826b4 100+ error_setg_errno(errp, -ret, "blk_preadv failed");
5b15e2ec
FE
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) {
0af826b4
FE
133+ error_setg_errno(errp, -ret, "blk(_co)_pwritev failed");
134+ return -1;
5b15e2ec
FE
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);
214diff --git a/migration/channel-savevm-async.h b/migration/channel-savevm-async.h
215new file mode 100644
216index 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 */
271diff --git a/migration/meson.build b/migration/meson.build
bf251437 272index 0d1bb9f96e..8a142fc7a9 100644
5b15e2ec
FE
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',