]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/core/device.c
Merge pull request #17549 from yuwata/tiny-fixes
[thirdparty/systemd.git] / src / core / device.c
index 771239f53b60cf5bcf0f544e563b535bba4f94b9..9a1d88270d1de9aa41fd40d1aebeb5a13ed5e853 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: LGPL-2.1+ */
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
 
 #include <errno.h>
 #include <sys/epoll.h>
@@ -83,6 +83,8 @@ static int device_set_sysfs(Device *d, const char *sysfs) {
         }
 
         d->sysfs = TAKE_PTR(copy);
+        unit_add_to_dbus_queue(UNIT(d));
+
         return 0;
 }
 
@@ -116,7 +118,7 @@ static void device_done(Unit *u) {
 static int device_load(Unit *u) {
         int r;
 
-        r = unit_load_fragment_and_dropin_optional(u);
+        r = unit_load_fragment_and_dropin(u, false);
         if (r < 0)
                 return r;
 
@@ -374,7 +376,7 @@ static int device_add_udev_wants(Unit *u, sd_device *dev) {
         for (;;) {
                 _cleanup_free_ char *word = NULL, *k = NULL;
 
-                r = extract_first_word(&wants, &word, NULL, EXTRACT_QUOTES);
+                r = extract_first_word(&wants, &word, NULL, EXTRACT_UNQUOTE);
                 if (r == 0)
                         break;
                 if (r == -ENOMEM)
@@ -420,7 +422,7 @@ static int device_add_udev_wants(Unit *u, sd_device *dev) {
                 /* So here's a special hack, to compensate for the fact that the udev database's reload cycles are not
                  * synchronized with our own reload cycles: when we detect that the SYSTEMD_WANTS property of a device
                  * changes while the device unit is already up, let's manually trigger any new units listed in it not
-                 * seen before. This typically appens during the boot-time switch root transition, as udev devices
+                 * seen before. This typically happens during the boot-time switch root transition, as udev devices
                  * will generally already be up in the initrd, but SYSTEMD_WANTS properties get then added through udev
                  * rules only available on the host system, and thus only when the initial udev coldplug trigger runs.
                  *
@@ -439,10 +441,7 @@ static int device_add_udev_wants(Unit *u, sd_device *dev) {
                 }
         }
 
-        strv_free(d->wants_property);
-        d->wants_property = TAKE_PTR(added);
-
-        return 0;
+        return strv_free_and_replace(d->wants_property, added);
 }
 
 static bool device_is_bound_by_mounts(Device *d, sd_device *dev) {
@@ -466,13 +465,12 @@ static bool device_is_bound_by_mounts(Device *d, sd_device *dev) {
 
 static void device_upgrade_mount_deps(Unit *u) {
         Unit *other;
-        Iterator i;
         void *v;
         int r;
 
         /* Let's upgrade Requires= to BindsTo= on us. (Used when SYSTEMD_MOUNT_DEVICE_BOUND is set) */
 
-        HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_REQUIRED_BY], i) {
+        HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_REQUIRED_BY]) {
                 if (other->type != UNIT_MOUNT)
                         continue;
 
@@ -525,7 +523,7 @@ static int device_setup_unit(Manager *m, sd_device *dev, const char *path, bool
 
                 delete = false;
 
-                /* Let's remove all dependencies generated due to udev properties. We'll readd whatever is configured
+                /* Let's remove all dependencies generated due to udev properties. We'll re-add whatever is configured
                  * now below. */
                 unit_remove_dependencies(u, UNIT_DEPENDENCY_UDEV);
         } else {
@@ -562,9 +560,6 @@ static int device_setup_unit(Manager *m, sd_device *dev, const char *path, bool
         if (dev && device_is_bound_by_mounts(DEVICE(u), dev))
                 device_upgrade_mount_deps(u);
 
-        /* Note that this won't dispatch the load queue, the caller has to do that if needed and appropriate */
-        unit_add_to_dbus_queue(u);
-
         return 0;
 
 fail:
@@ -626,7 +621,7 @@ static int device_process_new(Manager *m, sd_device *dev) {
         for (;;) {
                 _cleanup_free_ char *word = NULL;
 
-                r = extract_first_word(&alias, &word, NULL, EXTRACT_QUOTES);
+                r = extract_first_word(&alias, &word, NULL, EXTRACT_UNQUOTE);
                 if (r == 0)
                         break;
                 if (r == -ENOMEM)
@@ -666,9 +661,13 @@ static void device_found_changed(Device *d, DeviceFound previous, DeviceFound no
 }
 
 static void device_update_found_one(Device *d, DeviceFound found, DeviceFound mask) {
+        Manager *m;
+
         assert(d);
 
-        if (MANAGER_IS_RUNNING(UNIT(d)->manager)) {
+        m = UNIT(d)->manager;
+
+        if (MANAGER_IS_RUNNING(m) && (m->honor_device_enumeration || MANAGER_IS_USER(m))) {
                 DeviceFound n, previous;
 
                 /* When we are already running, then apply the new mask right-away, and trigger state changes
@@ -733,6 +732,10 @@ static bool device_is_ready(sd_device *dev) {
         if (device_is_renaming(dev) > 0)
                 return false;
 
+        /* Is it really tagged as 'systemd' right now? */
+        if (sd_device_has_current_tag(dev, "systemd") <= 0)
+                return false;
+
         if (sd_device_get_property_value(dev, "SYSTEMD_READY", &ready) < 0)
                 return true;
 
@@ -891,6 +894,29 @@ static void device_propagate_reload_by_sysfs(Manager *m, const char *sysfs) {
         }
 }
 
+static int device_remove_old(Manager *m, sd_device *dev) {
+        _cleanup_free_ char *syspath_old = NULL, *e = NULL;
+        const char *devpath_old;
+        int r;
+
+        r = sd_device_get_property_value(dev, "DEVPATH_OLD", &devpath_old);
+        if (r < 0) {
+                log_device_debug_errno(dev, r, "Failed to get DEVPATH_OLD= property on 'move' uevent, ignoring: %m");
+                return 0;
+        }
+
+        syspath_old = path_join("/sys", devpath_old);
+        if (!syspath_old)
+                return log_oom();
+
+        r = unit_name_from_path(syspath_old, ".device", &e);
+        if (r < 0)
+                return log_device_error_errno(dev, r, "Failed to generate unit name from old device path: %m");
+
+        device_update_found_by_sysfs(m, syspath_old, 0, DEVICE_FOUND_UDEV|DEVICE_FOUND_MOUNT|DEVICE_FOUND_SWAP);
+        return 0;
+}
+
 static int device_dispatch_io(sd_device_monitor *monitor, sd_device *dev, void *userdata) {
         Manager *m = userdata;
         DeviceAction action;
@@ -912,20 +938,22 @@ static int device_dispatch_io(sd_device_monitor *monitor, sd_device *dev, void *
                 return 0;
         }
 
-        if (action == DEVICE_ACTION_CHANGE)
+        if (!IN_SET(action, DEVICE_ACTION_ADD, DEVICE_ACTION_REMOVE, DEVICE_ACTION_MOVE))
                 device_propagate_reload_by_sysfs(m, sysfs);
 
-        /* A change event can signal that a device is becoming ready, in particular if
-         * the device is using the SYSTEMD_READY logic in udev
-         * so we need to reach the else block of the follwing if, even for change events */
+        if (action == DEVICE_ACTION_MOVE)
+                (void) device_remove_old(m, dev);
+
+        /* A change event can signal that a device is becoming ready, in particular if the device is using
+         * the SYSTEMD_READY logic in udev so we need to reach the else block of the following if, even for
+         * change events */
         if (action == DEVICE_ACTION_REMOVE) {
                 r = swap_process_device_remove(m, dev);
                 if (r < 0)
                         log_device_warning_errno(dev, r, "Failed to process swap device remove event, ignoring: %m");
 
-                /* If we get notified that a device was removed by
-                 * udev, then it's completely gone, hence unset all
-                 * found bits */
+                /* If we get notified that a device was removed by udev, then it's completely gone, hence
+                 * unset all found bits */
                 device_update_found_by_sysfs(m, sysfs, 0, DEVICE_FOUND_UDEV|DEVICE_FOUND_MOUNT|DEVICE_FOUND_SWAP);
 
         } else if (device_is_ready(dev)) {
@@ -941,13 +969,10 @@ static int device_dispatch_io(sd_device_monitor *monitor, sd_device *dev, void *
                 /* The device is found now, set the udev found bit */
                 device_update_found_by_sysfs(m, sysfs, DEVICE_FOUND_UDEV, DEVICE_FOUND_UDEV);
 
-        } else {
-                /* The device is nominally around, but not ready for
-                 * us. Hence unset the udev bit, but leave the rest
-                 * around. */
-
+        } else
+                /* The device is nominally around, but not ready for us. Hence unset the udev bit, but leave
+                 * the rest around. */
                 device_update_found_by_sysfs(m, sysfs, 0, DEVICE_FOUND_UDEV);
-        }
 
         return 0;
 }
@@ -1077,8 +1102,6 @@ const UnitVTable device_vtable = {
         .active_state = device_active_state,
         .sub_state_to_string = device_sub_state_to_string,
 
-        .bus_vtable = bus_device_vtable,
-
         .following = device_following,
         .following_set = device_following_set,