[libvirt] [PATCH REPOST v2 2/3] qemu: Use nodedev callback mechanism to to get a nodedev data

John Ferlan jferlan at redhat.com
Tue Feb 21 16:33:27 UTC 2017


Using the nodedev driver callback mechanism - allow qemu to be
notified whenever a nodedev is added/removed.

Keep track of the node devices in a hash table rather than requiring
a connection in order to get specific information about a node device
that qemu would eventually like to keep track of.

Signed-off-by: John Ferlan <jferlan at redhat.com>
---
 src/qemu/qemu_conf.c   | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
 src/qemu/qemu_conf.h   | 14 ++++++++++++++
 src/qemu/qemu_driver.c | 41 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 103 insertions(+)

diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index b5b0645..476179f 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -1619,3 +1619,51 @@ qemuGetDomainHupageMemPath(const virDomainDef *def,
 
     return 0;
 }
+
+
+/**
+ * @driver: qemu driver pointer
+ * @def: Node device definition
+ * @enumeration: boolean for emumeration indication
+ *
+ * Taking the @def from the node device driver, add the device to
+ * the qemu node device hash table. The @enumeration is true when
+ * this callback is called from the node device enumeration and false
+ * when called when the @def was added to the node device.
+ *
+ * Returns -1 on failure, 0 on adding device name, 1 on already added name
+ */
+int
+qemuNodeDeviceEntryAdd(virQEMUDriverPtr driver,
+                       virNodeDeviceDefPtr def,
+                       bool enumerate)
+{
+    VIR_DEBUG("Attempt to add name='%s', parent='%s' enumerate=%d",
+              def->name, def->parent, enumerate);
+
+    if (!virHashLookup(driver->nodeDevices, def->name)) {
+        if (virHashAddEntry(driver->nodeDevices, def->name, NULL) < 0)
+            return -1;
+        return 0;
+    }
+    return 1;
+}
+
+
+/**
+ * @driver: qemu driver pointer
+ * @def: node device definition
+ *
+ * Remove the definition from qemu's node device hash table.
+ *
+ * Returns 0 on success, -1 on failure
+ */
+int
+qemuNodeDeviceEntryRemove(virQEMUDriverPtr driver,
+                          virNodeDeviceDefPtr def)
+{
+    VIR_DEBUG("Attempt to remove name='%s' parent='%s'",
+              def->name, def->parent);
+
+    return virHashRemoveEntry(driver->nodeDevices, def->name);
+}
diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
index e585f81..d47c9cc 100644
--- a/src/qemu/qemu_conf.h
+++ b/src/qemu/qemu_conf.h
@@ -32,6 +32,7 @@
 # include "network_conf.h"
 # include "domain_conf.h"
 # include "snapshot_conf.h"
+# include "node_device_conf.h"
 # include "domain_event.h"
 # include "virthread.h"
 # include "security/security_manager.h"
@@ -255,6 +256,9 @@ struct _virQEMUDriver {
     virHashTablePtr sharedDevices;
 
     /* Immutable pointer, self-locking APIs */
+    virHashTablePtr nodeDevices;
+
+    /* Immutable pointer, self-locking APIs */
     virPortAllocatorPtr remotePorts;
 
     /* Immutable pointer, self-locking APIs */
@@ -351,4 +355,14 @@ int qemuGetDomainHupageMemPath(const virDomainDef *def,
                                virQEMUDriverConfigPtr cfg,
                                unsigned long long pagesize,
                                char **memPath);
+
+void qemuNodeDeviceEntryFree(void *payload, const void *name);
+
+int qemuNodeDeviceEntryAdd(virQEMUDriverPtr driver,
+                           virNodeDeviceDefPtr def,
+                           bool enumerate);
+
+int qemuNodeDeviceEntryRemove(virQEMUDriverPtr driver,
+                              virNodeDeviceDefPtr def);
+
 #endif /* __QEMUD_CONF_H */
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 6e1e3d4..546fea7 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -197,6 +197,28 @@ static virNWFilterCallbackDriver qemuCallbackDriver = {
 };
 
 
+static int
+qemuNodeDeviceAdd(virNodeDeviceDefPtr def,
+                  bool enumerate)
+{
+    return qemuNodeDeviceEntryAdd(qemu_driver, def, enumerate);
+}
+
+
+static int
+qemuNodeDeviceRemove(virNodeDeviceDefPtr def)
+{
+    return qemuNodeDeviceEntryRemove(qemu_driver, def);
+}
+
+
+static virNodeDeviceCallbackDriver qemuNodedevCallbackDriver = {
+    .name = QEMU_DRIVER_NAME,
+    .nodeDeviceAdd = qemuNodeDeviceAdd,
+    .nodeDeviceRemove = qemuNodeDeviceRemove,
+};
+
+
 struct qemuAutostartData {
     virQEMUDriverPtr driver;
     virConnectPtr conn;
@@ -638,6 +660,7 @@ qemuStateInitialize(bool privileged,
     char *driverConf = NULL;
     virConnectPtr conn = NULL;
     virQEMUDriverConfigPtr cfg;
+    virNodedevEnumerateAddDevices nodedevEnumCb;
     uid_t run_uid = -1;
     gid_t run_gid = -1;
     char *hugepagePath = NULL;
@@ -776,6 +799,23 @@ qemuStateInitialize(bool privileged,
     if (!(qemu_driver->sharedDevices = virHashCreate(30, qemuSharedDeviceEntryFree)))
         goto error;
 
+    /* Create a hash table to keep track of node device's by name */
+    if (!(qemu_driver->nodeDevices = virHashCreate(100, NULL)))
+        goto error;
+
+    /* Set up a callback mechanism with the node device conf code to get
+     * called whenever a node device is added or removed. */
+    if (!(nodedevEnumCb =
+          virNodeDeviceRegisterCallbackDriver(&qemuNodedevCallbackDriver)))
+        goto error;
+
+    /* Setting the add/remove callback first ensures that there is no
+     * window of opportunity for a device to be added after enumeration
+     * is complete, but before the callback is in place. So, set the
+     * callback first, then do the enumeration. */
+    if (nodedevEnumCb(qemuNodeDeviceAdd) < 0)
+        goto error;
+
     if (qemuMigrationErrorInit(qemu_driver) < 0)
         goto error;
 
@@ -1075,6 +1115,7 @@ qemuStateCleanup(void)
         return -1;
 
     virNWFilterUnRegisterCallbackDriver(&qemuCallbackDriver);
+    virNodeDeviceUnregisterCallbackDriver(&qemuNodedevCallbackDriver);
     virThreadPoolFree(qemu_driver->workerPool);
     virObjectUnref(qemu_driver->config);
     virObjectUnref(qemu_driver->hostdevMgr);
-- 
2.9.3




More information about the libvir-list mailing list