]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sd-device: make cloned sd_device object can read udev database without uevent file 19815/head
authorYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 4 Jun 2021 05:56:21 +0000 (14:56 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Sat, 5 Jun 2021 09:05:26 +0000 (18:05 +0900)
Some devices sent CHANGE and REMOVE uevent simultaneously.
To support that such device read udev database, let's copy minimal set of
properties which requires to read the database.

Fixes #19788.

src/libsystemd/sd-device/device-private.c

index 3307bb9db61fdb646c29f4d6b2f7bca731aebac3..7ec3f6f0d6b87abef0d485575d5a601f8a7eb036 100644 (file)
@@ -751,7 +751,7 @@ int device_rename(sd_device *device, const char *name) {
 
 int device_shallow_clone(sd_device *old_device, sd_device **new_device) {
         _cleanup_(sd_device_unrefp) sd_device *ret = NULL;
-        const char *subsystem;
+        const char *val;
         int r;
 
         assert(old_device);
@@ -765,17 +765,43 @@ int device_shallow_clone(sd_device *old_device, sd_device **new_device) {
         if (r < 0)
                 return r;
 
-        if (sd_device_get_subsystem(old_device, &subsystem) >= 0) {
-                r = device_set_subsystem(ret, subsystem);
+        if (sd_device_get_subsystem(old_device, &val) >= 0) {
+                r = device_set_subsystem(ret, val);
                 if (r < 0)
                         return r;
+
+                if (streq(val, "drivers")) {
+                        ret->driver_subsystem = strdup(old_device->driver_subsystem);
+                        if (!ret->driver_subsystem)
+                                return -ENOMEM;
+                }
         } else
                 ret->subsystem_set = true;
 
-        ret->devnum = old_device->devnum;
+        /* The device may be already removed. Let's copy minimal set of information to make
+         * device_get_device_id() work without uevent file. */
 
-        *new_device = TAKE_PTR(ret);
+        if (sd_device_get_property_value(old_device, "IFINDEX", &val) >= 0) {
+                r = device_set_ifindex(ret, val);
+                if (r < 0)
+                        return r;
+        }
+
+        if (sd_device_get_property_value(old_device, "MAJOR", &val) >= 0) {
+                const char *minor = NULL;
 
+                (void) sd_device_get_property_value(old_device, "MINOR", &minor);
+                r = device_set_devnum(ret, val, minor);
+                if (r < 0)
+                        return r;
+        }
+
+        /* And then read uevent file, but ignore errors, as some devices seem to return a spurious
+         * error on read, e.g. -ENODEV, and even if ifindex or devnum is set in the above,
+         * sd_device_get_ifindex() or sd_device_get_devnum() fails. See. #19788. */
+        (void) device_read_uevent_file(ret);
+
+        *new_device = TAKE_PTR(ret);
         return 0;
 }