@@ -1550,3 +1550,18 @@
##
{ 'command': 'query-vm-generation-id', 'returns': 'GuidInfo' }
+##
+# @yank:
+#
+# Recover from hanging qemu by calling yank functions.
+#
+# Returns: nothing.
+#
+# Example:
+#
+# -> { "execute": "yank" }
+# <- { "return": {} }
+#
+# Since: 5.1
+##
+{ 'command': 'yank', 'allow-oob': true }
@@ -112,6 +112,7 @@
#include "qapi/qmp/qerror.h"
#include "sysemu/iothread.h"
#include "qemu/guest-random.h"
+#include "yank.h"
#define MAX_VIRTIO_CONSOLES 1
@@ -2906,6 +2907,7 @@ void qemu_init(int argc, char **argv, char **envp)
precopy_infrastructure_init();
postcopy_infrastructure_init();
monitor_init_globals();
+ yank_init();
if (qcrypto_init(&err) < 0) {
error_reportf_err(err, "cannot initialize crypto: ");
new file mode 100644
@@ -0,0 +1,75 @@
+/*
+ * QEMU yank feature
+ *
+ * Copyright (c) Lukas Straub <lukasstraub2@web.de>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu/thread.h"
+#include "qemu/queue.h"
+#include "yank.h"
+
+struct YankFuncAndParam {
+ YankFn *func;
+ void *opaque;
+ QLIST_ENTRY(YankFuncAndParam) next;
+};
+
+static QemuMutex lock;
+static QLIST_HEAD(qlisthead, YankFuncAndParam) head
+ = QLIST_HEAD_INITIALIZER(head);
+
+void yank_register_function(YankFn *func, void *opaque)
+{
+ struct YankFuncAndParam *tmp = g_malloc(sizeof(struct YankFuncAndParam));
+ tmp->func = func;
+ tmp->opaque = opaque;
+
+ qemu_mutex_lock(&lock);
+ QLIST_INSERT_HEAD(&head, tmp, next);
+ qemu_mutex_unlock(&lock);
+}
+
+void yank_unregister_function(YankFn *func, void *opaque)
+{
+ qemu_mutex_lock(&lock);
+
+ struct YankFuncAndParam *tmp;
+ QLIST_FOREACH(tmp, &head, next) {
+ if (tmp->func == func && tmp->opaque == opaque) {
+ QLIST_REMOVE(tmp, next);
+ g_free(tmp);
+ qemu_mutex_unlock(&lock);
+ return;
+ }
+ }
+
+ abort();
+}
+
+void yank_call_functions(void)
+{
+ qemu_mutex_lock(&lock);
+
+ struct YankFuncAndParam *tmp;
+ QLIST_FOREACH(tmp, &head, next) {
+ tmp->func(tmp->opaque);
+ }
+
+ qemu_mutex_unlock(&lock);
+}
+
+void qmp_yank(Error **errp)
+{
+ yank_call_functions();
+}
+
+void yank_init(void)
+{
+ qemu_mutex_init(&lock);
+ QLIST_INIT(&head);
+}
new file mode 100644
@@ -0,0 +1,12 @@
+
+#ifndef YANK_H
+#define YANK_H
+
+typedef void (YankFn) (void *opaque);
+
+void yank_register_function(YankFn *func, void *opaque);
+void yank_unregister_function(YankFn *func, void *opaque);
+void yank_call_functions(void);
+void yank_init(void);
+void qmp_yank(Error **errp);
+#endif
The yank feature allows to recover from hanging qemu by "yanking" at various parts. Other qemu systems can register yank functions which will be called by the 'yank' out-of-band qmp command. Signed-off-by: Lukas Straub <lukasstraub2@web.de> --- qapi/misc.json | 15 ++++++++++ softmmu/vl.c | 2 ++ yank.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++ yank.h | 12 ++++++++ 4 files changed, 104 insertions(+) create mode 100644 yank.c create mode 100644 yank.h