diff mbox series

[V2,19/22] monitor: cpr support

Message ID 1609861330-129855-20-git-send-email-steven.sistare@oracle.com (mailing list archive)
State New, archived
Headers show
Series Live Update | expand

Commit Message

Steven Sistare Jan. 5, 2021, 3:42 p.m. UTC
A monitor socket requires special treatment.  Save and restore the
qmp negotiation status.  Stop the monitor's iothread in cpsave. Otherwise,
the thread will detect the close of the monitor socket and call unsetenv_fd,which modifies environ and races with execv which uses environ.

Signed-off-by: Mark Kanda <mark.kanda@oracle.com>
Signed-off-by: Steve Sistare <steven.sistare@oracle.com>
---
 include/monitor/monitor.h |  2 ++
 migration/cpr.c           |  2 ++
 monitor/monitor.c         |  5 +++++
 monitor/qmp.c             | 43 +++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 52 insertions(+)
diff mbox series

Patch

diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h
index 1018d75..5456cff 100644
--- a/include/monitor/monitor.h
+++ b/include/monitor/monitor.h
@@ -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);
diff --git a/migration/cpr.c b/migration/cpr.c
index de85d56..0f49c7d 100644
--- a/migration/cpr.c
+++ b/migration/cpr.c
@@ -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();
     }
diff --git a/monitor/monitor.c b/monitor/monitor.c
index b385a3d..1bda67c 100644
--- a/monitor/monitor.c
+++ b/monitor/monitor.c
@@ -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,
diff --git a/monitor/qmp.c b/monitor/qmp.c
index d433cea..d7eeab1 100644
--- a/monitor/qmp.c
+++ b/monitor/qmp.c
@@ -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);
+        }
+    }
 }