From: Yu Watanabe Date: Fri, 4 Jun 2021 05:56:21 +0000 (+0900) Subject: sd-device: make cloned sd_device object can read udev database without uevent file X-Git-Tag: v249-rc1~84^2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=381f6d4ba5551898e7ff19189485072b94879281;p=thirdparty%2Fsystemd.git 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. --- 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; }