@@ -22,6 +22,8 @@ void monitor_init_hmp(Chardev *chr, bool use_readline, Error **errp);
int monitor_init(MonitorOptions *opts, bool allow_hmp, Error **errp);
int monitor_init_opts(QemuOpts *opts, Error **errp);
void monitor_cleanup(void);
+void monitor_iothread_stop(void);
+void monitor_cprsave(void);
int monitor_suspend(Monitor *mon);
void monitor_resume(Monitor *mon);
@@ -137,9 +137,11 @@ void cprsave(const char *file, CprMode mode, Error **errp)
if (vfio_cprsave()) {
goto err;
}
+ monitor_iothread_stop();
walkenv(FD_PREFIX, preserve_fd, 0);
vhost_dev_reset_all();
qemu_term_exit();
+ monitor_cprsave();
setenv("QEMU_START_FREEZE", "", 1);
qemu_system_exec_request();
}
@@ -591,6 +591,11 @@ void monitor_cleanup(void)
}
}
+void monitor_iothread_stop(void)
+{
+ iothread_stop(mon_iothread);
+}
+
static void monitor_qapi_event_init(void)
{
monitor_qapi_event_state = g_hash_table_new(qapi_event_throttle_hash,
@@ -33,6 +33,7 @@
#include "qapi/qmp/qlist.h"
#include "qapi/qmp/qstring.h"
#include "trace.h"
+#include "qemu/env.h"
struct QMPRequest {
/* Owner of the request */
@@ -398,6 +399,21 @@ static void monitor_qmp_setup_handlers_bh(void *opaque)
monitor_list_append(&mon->common);
}
+static void setenv_qmp(const char *name, bool val)
+{
+ setenv_bool(name, val);
+}
+
+static bool getenv_qmp(const char *name)
+{
+ bool ret = getenv_bool(name);
+ if (ret != -1) {
+ unsetenv_bool(name);
+ return ret;
+ }
+ return false;
+}
+
void monitor_init_qmp(Chardev *chr, bool pretty, Error **errp)
{
MonitorQMP *mon = g_new0(MonitorQMP, 1);
@@ -438,4 +454,31 @@ void monitor_init_qmp(Chardev *chr, bool pretty, Error **errp)
NULL, &mon->common, NULL, true);
monitor_list_append(&mon->common);
}
+
+ /*
+ * If a chr->label qmp env var is true, this is a restored qmp
+ * connection with capabilities negotiated.
+ */
+ if (getenv_qmp(chr->label) == true) {
+ mon->commands = &qmp_commands;
+ }
+}
+
+/* Save the result of capability negotiation in the environment */
+
+void monitor_cprsave(void)
+{
+ Monitor *mon;
+ MonitorQMP *qmp_mon;
+
+ QTAILQ_FOREACH(mon, &mon_list, entry) {
+ if (!monitor_is_qmp(mon)) {
+ continue;
+ }
+
+ qmp_mon = container_of(mon, MonitorQMP, common);
+ if (qmp_mon->commands == &qmp_commands) {
+ setenv_qmp(mon->chr.chr->label, true);
+ }
+ }
}