[libvirt] [PATCH v3 1/6] nodedev: Introduce udevCheckMonitorFD helper function

Erik Skultety eskultet at redhat.com
Thu Aug 24 11:23:27 UTC 2017


We need to perform some sanity checks on the udev monitor before every
use so that we know nothing changed in the meantime. The reason for
moving the code to a separate function is to be able to perform the same
check from a worker thread that will replace the udevEventHandleCallback
in terms of poking udev for device events.

Signed-off-by: Erik Skultety <eskultet at redhat.com>
---
 src/node_device/node_device_udev.c | 57 ++++++++++++++++++++++++++------------
 1 file changed, 39 insertions(+), 18 deletions(-)

diff --git a/src/node_device/node_device_udev.c b/src/node_device/node_device_udev.c
index f4177455c..465d272ba 100644
--- a/src/node_device/node_device_udev.c
+++ b/src/node_device/node_device_udev.c
@@ -1615,47 +1615,68 @@ udevHandleOneDevice(struct udev_device *device)
 }
 
 
-static void
-udevEventHandleCallback(int watch ATTRIBUTE_UNUSED,
-                        int fd,
-                        int events ATTRIBUTE_UNUSED,
-                        void *data ATTRIBUTE_UNUSED)
+/* the caller must be holding the driver lock prior to calling this function */
+static bool
+udevCheckMonitorFD(struct udev_monitor *udev_monitor, int fd)
 {
-    struct udev_device *device = NULL;
-    struct udev_monitor *udev_monitor = DRV_STATE_UDEV_MONITOR(driver);
-    int udev_fd = -1;
+    int real_fd = -1;
 
-    udev_fd = udev_monitor_get_fd(udev_monitor);
-    if (fd != udev_fd) {
+    /* sanity check that the monitor socket hasn't changed */
+    real_fd = udev_monitor_get_fd(udev_monitor);
+
+    if (real_fd != fd) {
         udevPrivate *priv = driver->privateData;
 
         virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("File descriptor returned by udev %d does not "
                          "match node device file descriptor %d"),
-                       fd, udev_fd);
+                       real_fd, fd);
 
-        /* this is a non-recoverable error, let's remove the handle, so that we
-         * don't get in here again because of some spurious behaviour and report
-         * the same error multiple times
+        /* this is a non-recoverable error, thus the event handle has to be
+         * removed, so that we don't get into the handler again because of some
+         * spurious behaviour
          */
         virEventRemoveHandle(priv->watch);
         priv->watch = -1;
 
-        goto cleanup;
+        return false;
     }
 
-    device = udev_monitor_receive_device(udev_monitor);
-    if (device == NULL) {
+    return true;
+}
+
+
+static void
+udevEventHandleCallback(int watch ATTRIBUTE_UNUSED,
+                        int fd,
+                        int events ATTRIBUTE_UNUSED,
+                        void *data ATTRIBUTE_UNUSED)
+{
+    struct udev_device *device = NULL;
+    struct udev_monitor *udev_monitor = NULL;
+
+    nodeDeviceLock();
+    udev_monitor = DRV_STATE_UDEV_MONITOR(driver);
+
+    if (!udevCheckMonitorFD(udev_monitor, fd))
+        goto unlock;
+
+    if (!(device = udev_monitor_receive_device(udev_monitor))) {
         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                        _("udev_monitor_receive_device returned NULL"));
-        goto cleanup;
+        goto unlock;
     }
 
+    nodeDeviceUnlock();
     udevHandleOneDevice(device);
 
  cleanup:
     udev_device_unref(device);
     return;
+
+ unlock:
+    nodeDeviceUnlock();
+    goto cleanup;
 }
 
 
-- 
2.13.3




More information about the libvir-list mailing list