diff mbox series

[RFC,v1,14/26] kvm: vmi: allow only one instance of the introspection object

Message ID 20200415005938.23895-15-alazar@bitdefender.com
State New
Headers show
Series None | expand

Commit Message

Adalbert Lazăr April 15, 2020, 12:59 a.m. UTC
Because only one introspection tool must introspect a VM at a given time,
we block the completion of the second instance.

Signed-off-by: Adalbert Lazăr <alazar@bitdefender.com>
---
 accel/kvm/vmi.c | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)
diff mbox series

Patch

diff --git a/accel/kvm/vmi.c b/accel/kvm/vmi.c
index 2ce8a60565..54c56c6e13 100644
--- a/accel/kvm/vmi.c
+++ b/accel/kvm/vmi.c
@@ -52,10 +52,18 @@  typedef struct VMIntrospection {
     bool kvmi_hooked;
 } VMIntrospection;
 
+typedef struct VMIntrospectionClass {
+    ObjectClass parent_class;
+    uint32_t instance_counter;
+    VMIntrospection *uniq;
+} VMIntrospectionClass;
+
 #define TYPE_VM_INTROSPECTION "introspection"
 
 #define VM_INTROSPECTION(obj) \
     OBJECT_CHECK(VMIntrospection, (obj), TYPE_VM_INTROSPECTION)
+#define VM_INTROSPECTION_CLASS(class) \
+    OBJECT_CLASS_CHECK(VMIntrospectionClass, (class), TYPE_VM_INTROSPECTION)
 
 static Error *vm_introspection_init(VMIntrospection *i);
 
@@ -81,8 +89,14 @@  static void update_vm_start_time(VMIntrospection *i)
 
 static void complete(UserCreatable *uc, Error **errp)
 {
+    VMIntrospectionClass *ic = VM_INTROSPECTION_CLASS(OBJECT(uc)->class);
     VMIntrospection *i = VM_INTROSPECTION(uc);
 
+    if (ic->instance_counter > 1) {
+        error_setg(errp, "VMI: only one introspection object can be created");
+        return;
+    }
+
     if (!i->chardevid) {
         error_setg(errp, "VMI: chardev is not set");
         return;
@@ -106,6 +120,8 @@  static void complete(UserCreatable *uc, Error **errp)
         i->init_error = NULL;
         return;
     }
+
+    ic->uniq = i;
 }
 
 static void prop_set_chardev(Object *obj, const char *value, Error **errp)
@@ -168,8 +184,11 @@  static void class_init(ObjectClass *oc, void *data)
 
 static void instance_init(Object *obj)
 {
+    VMIntrospectionClass *ic = VM_INTROSPECTION_CLASS(obj->class);
     VMIntrospection *i = VM_INTROSPECTION(obj);
 
+    ic->instance_counter++;
+
     i->sock_fd = -1;
     i->created_from_command_line = (qdev_hotplug == false);
 
@@ -234,6 +253,7 @@  static void cancel_handshake_timer(VMIntrospection *i)
 
 static void instance_finalize(Object *obj)
 {
+    VMIntrospectionClass *ic = VM_INTROSPECTION_CLASS(obj->class);
     VMIntrospection *i = VM_INTROSPECTION(obj);
 
     g_free(i->chardevid);
@@ -248,12 +268,18 @@  static void instance_finalize(Object *obj)
     }
 
     error_free(i->init_error);
+
+    ic->instance_counter--;
+    if (!ic->instance_counter) {
+        ic->uniq = NULL;
+    }
 }
 
 static const TypeInfo info = {
     .name              = TYPE_VM_INTROSPECTION,
     .parent            = TYPE_OBJECT,
     .class_init        = class_init,
+    .class_size        = sizeof(VMIntrospectionClass),
     .instance_size     = sizeof(VMIntrospection),
     .instance_finalize = instance_finalize,
     .instance_init     = instance_init,