device : reload when udev generates a "changed" event (#6850)
authorBoucman <jeremy.rosen@enst-bretagne.fr>
Fri, 10 Nov 2017 16:00:32 +0000 (17:00 +0100)
committerLennart Poettering <lennart@poettering.net>
Fri, 10 Nov 2017 16:00:32 +0000 (17:00 +0100)
man/systemd.device.xml
src/core/device.c

index c60b9c0..6edf109 100644 (file)
     the escaping logic used to convert a file system path to a unit
     name see
     <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
+
+    <para>Device units will be reloaded by systemd whenever the
+    corresponding device generates a <literal>changed</literal> event.
+    Other units can use <varname>ReloadPropagatedFrom=</varname> to react
+    to that event</para>
+
   </refsect1>
 
   <refsect1>
index 87186f1..3915b26 100644 (file)
@@ -766,6 +766,26 @@ static int device_dispatch_io(sd_event_source *source, int fd, uint32_t revents,
                 return 0;
         }
 
+        if (streq(action, "change"))  {
+                _cleanup_free_ char *e = NULL;
+                Unit *u;
+
+                r = unit_name_from_path(sysfs, ".device", &e);
+                if (r < 0)
+                        log_error_errno(r, "Failed to generate unit name from device path: %m");
+                else {
+                        u = manager_get_unit(m, e);
+                        if (u && UNIT_VTABLE(u)->active_state(u) == UNIT_ACTIVE) {
+                                r = manager_propagate_reload(m, u, JOB_REPLACE, NULL);
+                                if (r < 0)
+                                        log_error_errno(r, "Failed to propagate reload: %m");
+                        }
+                }
+        }
+
+        /* 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 (streq(action, "remove"))  {
                 r = swap_process_device_remove(m, dev);
                 if (r < 0)