On Fri, Mar 26, 2021 at 11:48:10AM -0500, Jonathon Jongsma wrote:
We need to query mdevctl for changes to device definitions since an
administrator can define new devices by executing mdevctl outside of
libvirt.
In the future, mdevctl may add a way to signal device add/remove via
events, but for now we resort to a bit of a workaround: monitoring the
mdevctl config directory for changes to files. When a change is
detected, we query mdevctl and update our device list. The mdevctl
querying is handled in a throwaway thread, and these threads are
synchronized with a mutex.
Signed-off-by: Jonathon Jongsma <jjongsma(a)redhat.com>
---
...
+static void
+mdevctlEventHandleCallback(GFileMonitor *monitor G_GNUC_UNUSED,
+ GFile *file,
+ GFile *other_file G_GNUC_UNUSED,
+ GFileMonitorEvent event_type,
+ gpointer user_data)
+{
+ udevEventData *priv = user_data;
+ /* if a new directory appears, monitor that directory for changes */
+ if (event_type == G_FILE_MONITOR_EVENT_CREATED &&
+ g_file_query_file_type(file, G_FILE_QUERY_INFO_NONE, NULL) ==
+ G_FILE_TYPE_DIRECTORY) {
^probably better written as:
if (event_type == G_FILE_MONITOR_EVENT_CREATED) {
file_type = g_file_query_file_type(file, G_FILE_QUERY_INFO_NONE, NULL);
if (file_type == G_FILE_TYPE_DIRECTORY) {
...
}
}
+ GList *newmonitors = monitorFileRecursively(priv, file);
newline here for better optical code separation
+ virMutexLock(&priv->mdevctlLock);
+ priv->mdevctlMonitors = g_list_concat(priv->mdevctlMonitors,
newmonitors);
+ virMutexUnlock(&priv->mdevctlLock);
+ }
+
+ /* When mdevctl creates a device, it can result in multiple notify events
+ * emitted for a single logical change (e.g. several CHANGED events, or a
+ * CREATED and CHANGED event followed by CHANGES_DONE_HINT). To avoid
+ * spawning a mdevctl thread multiple times for a single logical
+ * configuration change, try to coalesce these changes by waiting for the
+ * CHANGES_DONE_HINT event. As a fallback, add a timeout to trigger the
+ * signal if that event never comes */
+ if (event_type != G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT) {
+ if (priv->mdevctlTimeout > 0)
+ virEventRemoveTimeout(priv->mdevctlTimeout);
+ priv->mdevctlTimeout = virEventAddTimeout(100, scheduleMdevctlHandler,
+ priv, NULL);
+ return;
+ }
+
+ scheduleMdevctlHandler(-1, priv);
+}
Reviewed-by: Erik Skultety <eskultet(a)redhat.com>