Blame SOURCES/kvm-monitor-fix-dangling-CPU-pointer.patch

4a2fec
From 062ffad79316d7c3a2ace6d96ffc1f90d61469ec Mon Sep 17 00:00:00 2001
4a2fec
From: Serhii Popovych <spopovyc@redhat.com>
4a2fec
Date: Wed, 8 Nov 2017 13:35:20 +0100
4a2fec
Subject: [PATCH 2/7] monitor: fix dangling CPU pointer
4a2fec
4a2fec
RH-Author: Serhii Popovych <spopovyc@redhat.com>
4a2fec
Message-id: <1510148120-54741-1-git-send-email-spopovyc@redhat.com>
4a2fec
Patchwork-id: 77520
4a2fec
O-Subject: [RHV7.5 qemu-kvm-rhev PATCH v2] monitor: fix dangling CPU pointer
4a2fec
Bugzilla: 1510001
4a2fec
RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
4a2fec
RH-Acked-by: David Hildenbrand <david@redhat.com>
4a2fec
RH-Acked-by: Peter Xu <peterx@redhat.com>
4a2fec
4a2fec
From: Greg Kurz <groug@kaod.org>
4a2fec
4a2fec
Test: replay case as described in comment 4 on bz: qemu does not crash
4a2fec
4a2fec
If a CPU selected with the "cpu" command is hot-unplugged then "info cpus"
4a2fec
causes QEMU to exit:
4a2fec
4a2fec
(qemu) device_del cpu1
4a2fec
(qemu) info cpus
4a2fec
qemu:qemu_cpu_kick_thread: No such process
4a2fec
4a2fec
This happens because "cpu" stores the pointer to the selected CPU into
4a2fec
the monitor structure. When the CPU is hot-unplugged, we end up with a
4a2fec
dangling pointer. The "info cpus" command then does:
4a2fec
4a2fec
hmp_info_cpus()
4a2fec
 monitor_get_cpu_index()
4a2fec
  mon_get_cpu()
4a2fec
   cpu_synchronize_state() <--- called with dangling pointer
4a2fec
4a2fec
This could cause a QEMU crash as well.
4a2fec
4a2fec
This patch switches the monitor to store the QOM path instead of a
4a2fec
pointer to the current CPU. The path is then resolved when needed.
4a2fec
If the resolution fails, we assume that the CPU was removed and the
4a2fec
path is resetted to the default (ie, path of first_cpu).
4a2fec
4a2fec
Reported-by: Satheesh Rajendran <sathnaga@linux.vnet.ibm.com>
4a2fec
Suggested-by: Igor Mammedov <imammedo@redhat.com>
4a2fec
Signed-off-by: Greg Kurz <groug@kaod.org>
4a2fec
Message-Id: <150822818243.26242.12993827911736928961.stgit@bahia.lan>
4a2fec
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
4a2fec
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
4a2fec
(cherry picked from commit 751f8cfe2a556b3ef49f6af2860e2d1d2a1ec66a)
4a2fec
Signed-off-by: Serhii Popovych <spopovyc@redhat.com>
4a2fec
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
4a2fec
---
4a2fec
 monitor.c | 23 ++++++++++++++++++-----
4a2fec
 1 file changed, 18 insertions(+), 5 deletions(-)
4a2fec
4a2fec
diff --git a/monitor.c b/monitor.c
4a2fec
index bade261..c0a8dbc 100644
4a2fec
--- a/monitor.c
4a2fec
+++ b/monitor.c
4a2fec
@@ -200,7 +200,7 @@ struct Monitor {
4a2fec
 
4a2fec
     ReadLineState *rs;
4a2fec
     MonitorQMP qmp;
4a2fec
-    CPUState *mon_cpu;
4a2fec
+    gchar *mon_cpu_path;
4a2fec
     BlockCompletionFunc *password_completion_cb;
4a2fec
     void *password_opaque;
4a2fec
     mon_cmd_t *cmd_table;
4a2fec
@@ -579,6 +579,7 @@ static void monitor_data_init(Monitor *mon)
4a2fec
 
4a2fec
 static void monitor_data_destroy(Monitor *mon)
4a2fec
 {
4a2fec
+    g_free(mon->mon_cpu_path);
4a2fec
     qemu_chr_fe_deinit(&mon->chr, false);
4a2fec
     if (monitor_is_qmp(mon)) {
4a2fec
         json_message_parser_destroy(&mon->qmp.parser);
4a2fec
@@ -1065,20 +1066,32 @@ int monitor_set_cpu(int cpu_index)
4a2fec
     if (cpu == NULL) {
4a2fec
         return -1;
4a2fec
     }
4a2fec
-    cur_mon->mon_cpu = cpu;
4a2fec
+    g_free(cur_mon->mon_cpu_path);
4a2fec
+    cur_mon->mon_cpu_path = object_get_canonical_path(OBJECT(cpu));
4a2fec
     return 0;
4a2fec
 }
4a2fec
 
4a2fec
 CPUState *mon_get_cpu(void)
4a2fec
 {
4a2fec
-    if (!cur_mon->mon_cpu) {
4a2fec
+    CPUState *cpu;
4a2fec
+
4a2fec
+    if (cur_mon->mon_cpu_path) {
4a2fec
+        cpu = (CPUState *) object_resolve_path_type(cur_mon->mon_cpu_path,
4a2fec
+                                                    TYPE_CPU, NULL);
4a2fec
+        if (!cpu) {
4a2fec
+            g_free(cur_mon->mon_cpu_path);
4a2fec
+            cur_mon->mon_cpu_path = NULL;
4a2fec
+        }
4a2fec
+    }
4a2fec
+    if (!cur_mon->mon_cpu_path) {
4a2fec
         if (!first_cpu) {
4a2fec
             return NULL;
4a2fec
         }
4a2fec
         monitor_set_cpu(first_cpu->cpu_index);
4a2fec
+        cpu = first_cpu;
4a2fec
     }
4a2fec
-    cpu_synchronize_state(cur_mon->mon_cpu);
4a2fec
-    return cur_mon->mon_cpu;
4a2fec
+    cpu_synchronize_state(cpu);
4a2fec
+    return cpu;
4a2fec
 }
4a2fec
 
4a2fec
 CPUArchState *mon_get_cpu_env(void)
4a2fec
-- 
4a2fec
1.8.3.1
4a2fec