From 3df2b4557a6951a7b381ae04f17655917d0ec8a1 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 4 Apr 2024 05:39:25 +0900 Subject: [PATCH 1/3] udev-util: rename device_is_processing() -> device_is_processed() And make it also check the existence of the udev database. --- src/network/networkd-link.c | 12 ++---------- src/shared/udev-util.c | 17 ++++++++++++++--- src/shared/udev-util.h | 2 +- 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 3e8aa9e37a..192e9df979 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -1630,9 +1630,9 @@ static int link_check_initialized(Link *link) { return 0; } - r = sd_device_get_is_initialized(device); + r = device_is_processed(device); if (r < 0) - return log_link_warning_errno(link, r, "Could not determine whether the device is initialized: %m"); + return log_link_warning_errno(link, r, "Could not determine whether the device is processed by udevd: %m"); if (r == 0) { /* not yet ready */ log_link_debug(link, "link pending udev initialization..."); @@ -1647,14 +1647,6 @@ static int link_check_initialized(Link *link) { return 0; } - r = device_is_processing(device); - if (r < 0) - return log_link_warning_errno(link, r, "Failed to determine whether the device is being processed: %m"); - if (r > 0) { - log_link_debug(link, "Interface is being processed by udevd, pending initialization."); - return 0; - } - return link_initialized(link, device); } diff --git a/src/shared/udev-util.c b/src/shared/udev-util.c index 0014b7236f..1934694035 100644 --- a/src/shared/udev-util.c +++ b/src/shared/udev-util.c @@ -237,16 +237,27 @@ int device_is_renaming(sd_device *dev) { return r; } -int device_is_processing(sd_device *dev) { +int device_is_processed(sd_device *dev) { int r; assert(dev); + /* sd_device_get_is_initialized() only checks if the udev database file exists. However, even if the + * database file exist, systemd-udevd may be still processing the device, e.g. when the udev rules + * for the device have RUN tokens. See issue #30056. Hence, to check if the device is really + * processed by systemd-udevd, we also need to read ID_PROCESSING property. */ + + r = sd_device_get_is_initialized(dev); + if (r <= 0) + return r; + r = device_get_property_bool(dev, "ID_PROCESSING"); if (r == -ENOENT) - return false; /* defaults to false */ + return true; /* If the property does not exist, then it means that the device is processed. */ + if (r < 0) + return r; - return r; + return !r; } bool device_for_action(sd_device *dev, sd_device_action_t a) { diff --git a/src/shared/udev-util.h b/src/shared/udev-util.h index 13710a3ec1..c21c4c158c 100644 --- a/src/shared/udev-util.h +++ b/src/shared/udev-util.h @@ -13,7 +13,7 @@ int udev_parse_config(void); int device_wait_for_initialization(sd_device *device, const char *subsystem, usec_t timeout_usec, sd_device **ret); int device_wait_for_devlink(const char *path, const char *subsystem, usec_t timeout_usec, sd_device **ret); int device_is_renaming(sd_device *dev); -int device_is_processing(sd_device *dev); +int device_is_processed(sd_device *dev); bool device_for_action(sd_device *dev, sd_device_action_t action); From 54e6172550226362e4b88fd297e09266f981ea27 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 4 Apr 2024 05:40:52 +0900 Subject: [PATCH 2/3] tree-wide: use device_is_processed() more --- src/nspawn/nspawn-network.c | 2 +- src/shared/udev-util.c | 4 ++-- src/udev/udevadm-wait.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/nspawn/nspawn-network.c b/src/nspawn/nspawn-network.c index 94e751cf65..e89f087aea 100644 --- a/src/nspawn/nspawn-network.c +++ b/src/nspawn/nspawn-network.c @@ -487,7 +487,7 @@ static int test_network_interface_initialized(const char *name) { if (r < 0) return log_error_errno(r, "Failed to get device %s: %m", name); - r = sd_device_get_is_initialized(d); + r = device_is_processed(d); if (r < 0) return log_error_errno(r, "Failed to determine whether interface %s is initialized: %m", name); if (r == 0) diff --git a/src/shared/udev-util.c b/src/shared/udev-util.c index 1934694035..15996ca724 100644 --- a/src/shared/udev-util.c +++ b/src/shared/udev-util.c @@ -139,7 +139,7 @@ static int device_wait_for_initialization_internal( } if (device) { - if (sd_device_get_is_initialized(device) > 0) { + if (device_is_processed(device) > 0) { if (ret) *ret = sd_device_ref(device); return 0; @@ -202,7 +202,7 @@ static int device_wait_for_initialization_internal( if (r < 0 && !ERRNO_IS_DEVICE_ABSENT(r)) return log_error_errno(r, "Failed to create sd-device object from %s: %m", devlink); } - if (device && sd_device_get_is_initialized(device) > 0) { + if (device && device_is_processed(device) > 0) { if (ret) *ret = sd_device_ref(device); return 0; diff --git a/src/udev/udevadm-wait.c b/src/udev/udevadm-wait.c index e6620c25dd..6ffc86bbf1 100644 --- a/src/udev/udevadm-wait.c +++ b/src/udev/udevadm-wait.c @@ -67,7 +67,7 @@ static int check_device(const char *path) { return r; if (arg_wait_until == WAIT_UNTIL_INITIALIZED) - return sd_device_get_is_initialized(dev); + return device_is_processed(dev); return true; } From 405be62f05d76f1845f347737b5972158c79dd3e Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 4 Apr 2024 05:53:55 +0900 Subject: [PATCH 3/3] tree-wide: refuse enumerated device with ID_PROCESSING=1 When enumerated devices are being processed by udevd, we will receive corresponding uevents later. So, we should not process devices in that case. --- src/core/device.c | 3 +++ src/home/homed-manager.c | 5 ++++- src/login/logind.c | 10 ++++++++-- src/storagetm/storagetm.c | 5 ++++- 4 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/core/device.c b/src/core/device.c index 93cab92b8c..d8567676a7 100644 --- a/src/core/device.c +++ b/src/core/device.c @@ -1051,6 +1051,9 @@ static void device_enumerate(Manager *m) { _cleanup_set_free_ Set *ready_units = NULL, *not_ready_units = NULL; Device *d; + if (device_is_processed(dev) <= 0) + continue; + if (device_setup_units(m, dev, &ready_units, ¬_ready_units) < 0) continue; diff --git a/src/home/homed-manager.c b/src/home/homed-manager.c index 5f345b3d40..90fd91c8a7 100644 --- a/src/home/homed-manager.c +++ b/src/home/homed-manager.c @@ -1365,8 +1365,11 @@ static int manager_enumerate_devices(Manager *m) { if (r < 0) return r; - FOREACH_DEVICE(e, d) + FOREACH_DEVICE(e, d) { + if (device_is_processed(d) <= 0) + continue; (void) manager_add_device(m, d); + } return 0; } diff --git a/src/login/logind.c b/src/login/logind.c index 4d3d0270ef..ac4b8602c4 100644 --- a/src/login/logind.c +++ b/src/login/logind.c @@ -194,8 +194,11 @@ static int manager_enumerate_devices(Manager *m) { r = 0; - FOREACH_DEVICE(e, d) + FOREACH_DEVICE(e, d) { + if (device_is_processed(d) <= 0) + continue; RET_GATHER(r, manager_process_seat_device(m, d)); + } return r; } @@ -225,8 +228,11 @@ static int manager_enumerate_buttons(Manager *m) { r = 0; - FOREACH_DEVICE(e, d) + FOREACH_DEVICE(e, d) { + if (device_is_processed(d) <= 0) + continue; RET_GATHER(r, manager_process_button_device(m, d)); + } return r; } diff --git a/src/storagetm/storagetm.c b/src/storagetm/storagetm.c index 62b78a350f..e060998829 100644 --- a/src/storagetm/storagetm.c +++ b/src/storagetm/storagetm.c @@ -1214,8 +1214,11 @@ static int run(int argc, char* argv[]) { if (r < 0) return log_error_errno(r, "Failed to exclude loop devices: %m"); - FOREACH_DEVICE(enumerator, device) + FOREACH_DEVICE(enumerator, device) { + if (device_is_processed(device) <= 0) + continue; device_added(&context, device); + } } _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;