From 381f6d4ba5551898e7ff19189485072b94879281 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 4 Jun 2021 14:56:21 +0900 Subject: [PATCH] sd-device: make cloned sd_device object can read udev database without uevent file 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 | 36 +++++++++++++++++++---- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/src/libsystemd/sd-device/device-private.c b/src/libsystemd/sd-device/device-private.c index 3307bb9db61..7ec3f6f0d6b 100644 --- a/src/libsystemd/sd-device/device-private.c +++ b/src/libsystemd/sd-device/device-private.c @@ -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; } -- 2.47.3