]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
core: split out device validation from device_found_node()
authorLennart Poettering <lennart@poettering.net>
Mon, 4 Jun 2018 19:35:30 +0000 (21:35 +0200)
committerLennart Poettering <lennart@poettering.net>
Thu, 7 Jun 2018 11:36:19 +0000 (13:36 +0200)
Let's separate the validate step out. Also, let's update some comments
which have long ceased to be true.

No change in behaviour.

src/core/device.c

index 26a5014e2827a3e418b3af8b70c530e4ccab881c..e296ffa418b402901c6fd4c9bbf8a93fb7d05851 100644 (file)
@@ -941,56 +941,76 @@ static bool device_supported(void) {
         return read_only <= 0;
 }
 
-void device_found_node(Manager *m, const char *node, DeviceFound found, DeviceFound mask) {
-        _cleanup_(udev_device_unrefp) struct udev_device *dev = NULL;
+static int validate_node(Manager *m, const char *node, struct udev_device **ret) {
         struct stat st;
 
+        assert(m);
+        assert(node);
+        assert(ret);
+
+        /* Validates a device node that showed up in /proc/swaps or /proc/self/mountinfo if it makes sense for us to
+         * track. Note that this validator is fine within missing device nodes, but not with badly set up ones! */
+
+        if (!path_startswith(node, "/dev")) {
+                *ret = NULL;
+                return 0; /* bad! */
+        }
+
+        if (stat(node, &st) < 0) {
+                if (errno != ENOENT)
+                        return log_error_errno(errno, "Failed to stat() device node file %s: %m", node);
+
+                *ret = NULL;
+                return 1; /* good! (though missing) */
+
+        } else {
+                _cleanup_(udev_device_unrefp) struct udev_device *dev = NULL;
+
+                if (!S_ISBLK(st.st_mode) && !S_ISCHR(st.st_mode)) {
+                        *ret = NULL;
+                        return 0; /* bad! */
+                }
+
+                dev = udev_device_new_from_devnum(m->udev, S_ISBLK(st.st_mode) ? 'b' : 'c', st.st_rdev);
+                if (!dev) {
+                        if (errno != ENOENT)
+                                return log_error_errno(errno, "Failed to get udev device from devnum %u:%u: %m", major(st.st_rdev), minor(st.st_rdev));
+
+                        *ret = NULL;
+                        return 1; /* good! (though missing) */
+                }
+
+                *ret = TAKE_PTR(dev);
+                return 1; /* good! */
+        }
+}
+
+void device_found_node(Manager *m, const char *node, DeviceFound found, DeviceFound mask) {
+        int r;
+
         assert(m);
         assert(node);
 
         if (!device_supported())
                 return;
 
-        /* This is called whenever we find a device referenced in
-         * /proc/swaps or /proc/self/mounts. Such a device might be
-         * mounted/enabled at a time where udev has not finished
-         * probing it yet, and we thus haven't learned about it
-         * yet. In this case we will set the device unit to
-         * "tentative" state. */
+        if (mask == 0)
+                return;
+
+        /* This is called whenever we find a device referenced in /proc/swaps or /proc/self/mounts. Such a device might
+         * be mounted/enabled at a time where udev has not finished probing it yet, and we thus haven't learned about
+         * it yet. In this case we will set the device unit to "tentative" state. */
 
         if ((found & mask) != 0) {
-                if (!path_startswith(node, "/dev"))
-                        return;
-
-                /* We make an extra check here, if the device node
-                 * actually exists. If it's missing, then this is an
-                 * indication that device was unplugged but is still
-                 * referenced in /proc/swaps or
-                 * /proc/self/mountinfo. Note that this check doesn't
-                 * really cover all cases where a device might be gone
-                 * away, since drives that can have a medium inserted
-                 * will still have a device node even when the medium
-                 * is not there... */
-
-                if (stat(node, &st) >= 0) {
-                        if (!S_ISBLK(st.st_mode) && !S_ISCHR(st.st_mode))
-                                return;
-
-                        dev = udev_device_new_from_devnum(m->udev, S_ISBLK(st.st_mode) ? 'b' : 'c', st.st_rdev);
-                        if (!dev && errno != ENOENT) {
-                                log_error_errno(errno, "Failed to get udev device from devnum %u:%u: %m", major(st.st_rdev), minor(st.st_rdev));
-                                return;
-                        }
+                _cleanup_(udev_device_unrefp) struct udev_device *dev = NULL;
 
-                } else if (errno != ENOENT) {
-                        log_error_errno(errno, "Failed to stat device node file %s: %m", node);
-                        return;
-                }
+                /* If the device is known in the kernel and newly appeared, then we'll create a device unit for it,
+                 * under the name referenced in /proc/swaps or /proc/self/mountinfo. But first, let's validate if
+                 * everything is alright with the device node. */
 
-                /* If the device is known in the kernel and newly
-                 * appeared, then we'll create a device unit for it,
-                 * under the name referenced in /proc/swaps or
-                 * /proc/self/mountinfo. */
+                r = validate_node(m, node, &dev);
+                if (r <= 0)
+                        return; /* Don't create a device unit for this if the device node is borked. */
 
                 (void) device_setup_unit(m, dev, node, false);
         }