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(a)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 0223a95..527c1bc 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -1607,3 +1607,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 91904ed..b8af74b 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 */
@@ -350,4 +354,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 89bc833..c05914b 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.7.4