]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sd-device: add API for triggering synthetic uevents with UUID
authorLennart Poettering <lennart@poettering.net>
Wed, 26 May 2021 14:09:18 +0000 (16:09 +0200)
committerLennart Poettering <lennart@poettering.net>
Wed, 26 May 2021 19:44:36 +0000 (21:44 +0200)
Since kernel 4.13 the kerne allows passing a UUID to generated uevents.
Optionally do so via a new sd_device_trigger_with_uuid() call, and add
sd_device_get_trigger_uuid() as helper to retrieve the UUID from a
uevent we receive.

This is useful for tracking uevents through the udev system, and waiting
for specific triggers.

(Note that the 4.13 patch allows passing arbitrary meta-info into the
uevent as well. This does not add an API for that, because I am not
convinced it makes sense — as it conflicts with our general rule that
events are "stateless" if you so will — and it complicates the interface
quite a bit).

This replaces #13881 in a way, which added a similar infra, but which
stalled, and whose synchronous settling APIs are somewhat problematic
and probably not material to merge.

src/libsystemd/libsystemd.sym
src/libsystemd/sd-device/sd-device.c
src/systemd/sd-device.h

index 996bf25d6c220e6ae987b46134681936b545ea4b..1606981e1e16de63215f4dff9509e404ebce3ca8 100644 (file)
@@ -757,4 +757,6 @@ global:
         sd_device_monitor_filter_add_match_sysattr;
         sd_device_monitor_filter_add_match_parent;
         sd_device_get_usec_initialized;
+        sd_device_trigger_with_uuid;
+        sd_device_get_trigger_uuid;
 } LIBSYSTEMD_248;
index 363e4f2dd0a0c56706bcdd9c148cd78b197b7b16..a5bd7d8d84dacd4918e89719b4f77fed097d6658 100644 (file)
@@ -16,6 +16,7 @@
 #include "fileio.h"
 #include "fs-util.h"
 #include "hashmap.h"
+#include "id128-util.h"
 #include "macro.h"
 #include "parse-util.h"
 #include "path-util.h"
@@ -1869,6 +1870,34 @@ _public_ int sd_device_get_property_value(sd_device *device, const char *key, co
         return 0;
 }
 
+_public_ int sd_device_get_trigger_uuid(sd_device *device, sd_id128_t *ret) {
+        const char *s;
+        sd_id128_t id;
+        int r;
+
+        assert_return(device, -EINVAL);
+
+        /* Retrieves the UUID attached to a uevent when triggering it from userspace via
+         * sd_device_trigger_with_uuid() or an equivalent interface. Returns -ENOENT if the record is not
+         * caused by a synthetic event and -ENODATA if it was but no UUID was specified */
+
+        r = sd_device_get_property_value(device, "SYNTH_UUID", &s);
+        if (r < 0)
+                return r;
+
+        if (streq(s, "0")) /* SYNTH_UUID=0 is set whenever a device is triggered by userspace without specifying a UUID */
+                return -ENODATA;
+
+        r = sd_id128_from_string(s, &id);
+        if (r < 0)
+                return r;
+
+        if (ret)
+                *ret = id;
+
+        return 0;
+}
+
 static int device_cache_sysattr_value(sd_device *device, const char *key, char *value) {
         _cleanup_free_ char *new_key = NULL, *old_value = NULL;
         int r;
@@ -2096,5 +2125,41 @@ _public_ int sd_device_trigger(sd_device *device, sd_device_action_t action) {
         if (!s)
                 return -EINVAL;
 
+        /* This uses the simple no-UUID interface of kernel < 4.13 */
         return sd_device_set_sysattr_value(device, "uevent", s);
 }
+
+_public_ int sd_device_trigger_with_uuid(
+                sd_device *device,
+                sd_device_action_t action,
+                sd_id128_t *ret_uuid) {
+
+        char buf[ID128_UUID_STRING_MAX];
+        const char *s, *j;
+        sd_id128_t u;
+        int r;
+
+        assert_return(device, -EINVAL);
+
+        /* If noone wants to know the UUID, use the simple interface from pre-4.13 times */
+        if (!ret_uuid)
+                return sd_device_trigger(device, action);
+
+        s = device_action_to_string(action);
+        if (!s)
+                return -EINVAL;
+
+        r = sd_id128_randomize(&u);
+        if (r < 0)
+                return r;
+
+        id128_to_uuid_string(u, buf);
+        j = strjoina(s, " ", buf);
+
+        r = sd_device_set_sysattr_value(device, "uevent", j);
+        if (r < 0)
+                return r;
+
+        *ret_uuid = u;
+        return 0;
+}
index 8b7b361295ecc9d023247850f07bf85b7278e2b9..04599ea3821a6561dff360b45a73e47c774dd33b 100644 (file)
@@ -24,6 +24,7 @@
 #include <sys/types.h>
 
 #include "sd-event.h"
+#include "sd-id128.h"
 
 #include "_sd-common.h"
 
@@ -96,11 +97,13 @@ const char *sd_device_get_sysattr_next(sd_device *device);
 int sd_device_has_tag(sd_device *device, const char *tag);
 int sd_device_has_current_tag(sd_device *device, const char *tag);
 int sd_device_get_property_value(sd_device *device, const char *key, const char **value);
+int sd_device_get_trigger_uuid(sd_device *device, sd_id128_t *ret);
 int sd_device_get_sysattr_value(sd_device *device, const char *sysattr, const char **_value);
 
 int sd_device_set_sysattr_value(sd_device *device, const char *sysattr, const char *value);
 int sd_device_set_sysattr_valuef(sd_device *device, const char *sysattr, const char *format, ...) _sd_printf_(3, 4);
 int sd_device_trigger(sd_device *device, sd_device_action_t action);
+int sd_device_trigger_with_uuid(sd_device *device, sd_device_action_t action, sd_id128_t *ret_uuid);
 
 /* device enumerator */