From 77ee1783ebc8385013e95161427e1f945691ced0 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 8 Jul 2020 17:51:55 +0200 Subject: [PATCH] udevadm: beef up deprecation log warning Let's add a catalog entry explaining further details. Most importantly though: talk to PID 1 directly, via the private D-Bus socket, so that this actually works correctly during early boot, where D-Bus is not around. --- catalog/systemd.catalog.in | 33 ++++++++++++++++ src/systemd/sd-messages.h | 5 +++ src/udev/udevadm-settle.c | 79 +++++++++++++++++++++++--------------- 3 files changed, 86 insertions(+), 31 deletions(-) diff --git a/catalog/systemd.catalog.in b/catalog/systemd.catalog.in index 1d3b62a2f4..056df00de8 100644 --- a/catalog/systemd.catalog.in +++ b/catalog/systemd.catalog.in @@ -484,3 +484,36 @@ It is strongly recommended to avoid running services under this user identity, in particular on systems using NFS or running containers. Allocate a user ID specific to this service, either statically via systemd-sysusers or dynamically via the DynamicUser= service setting. + +-- 1c0454c1bd2241e0ac6fefb4bc631433 +Subject: systemd-udev-settle.service is deprecated. +Defined-By: systemd +Support: %SUPPORT_URL% + +Usage of the systemd service unit systemd-udev-settle.service is deprecated. It +inserts artificial delays into the boot process without providing the +guarantees other subsystems traditionally assumed it provides. Relying on this +service is racy, and it is generally a bug to make use of it and depend on it. + +Traditionally, this service's job was to wait until all devices a system +possesses have been fully probed and initialized, delaying boot until this +phase is completed. However, today's systems and hardware generally don't work +this way anymore, hardware today may show up any time and take any time to be +probed and initialized. Thus, in the general case, it's no longer possible to +correctly delay boot until "all devices" have been processed, as it is not +clear what "all devices" means and when they have been found. This is in +particular the case if USB hardware or network-attached hardware is used. + +Modern software that requires some specific hardware (such as a network device +or block device) to operate should only wait for the specific devices it needs +to show up, and otherwise operate asynchronously initializing devices as they +appear during boot and during runtime without delaying the boot process. + +It is a defect of the software in question if it doesn't work this way, and +still pulls systemd-udev-settle.service into the boot process. + +Please file a bug report against the following units, with a request for it to +be updated to operate in a hotplug fashion without depending on +systemd-udev-settle.service: + + @OFFENDING_UNITS@ diff --git a/src/systemd/sd-messages.h b/src/systemd/sd-messages.h index 00846ea00b..a4e9680dc1 100644 --- a/src/systemd/sd-messages.h +++ b/src/systemd/sd-messages.h @@ -170,6 +170,11 @@ _SD_BEGIN_DECLARATIONS; #define SD_MESSAGE_NOBODY_USER_UNSUITABLE_STR \ SD_ID128_MAKE_STR(b4,80,32,5f,9c,39,4a,7b,80,2c,23,1e,51,a2,75,2c) +#define SD_MESSAGE_SYSTEMD_UDEV_SETTLE_DEPRECATED \ + SD_ID128_MAKE(1c,04,54,c1,bd,22,41,e0,ac,6f,ef,b4,bc,63,14,33) +#define SD_MESSAGE_SYSTEMD_UDEV_SETTLE_DEPRECATED_STR \ + SD_ID128_MAKE_STR(1c,04,54,c1,bd,22,41,e0,ac,6f,ef,b4,bc,63,14,33) + _SD_END_DECLARATIONS; #endif diff --git a/src/udev/udevadm-settle.c b/src/udev/udevadm-settle.c index 5730349ba5..66c7103d78 100644 --- a/src/udev/udevadm-settle.c +++ b/src/udev/udevadm-settle.c @@ -14,7 +14,9 @@ #include "sd-bus.h" #include "sd-login.h" +#include "sd-messages.h" +#include "bus-util.h" #include "io-util.h" #include "libudev-util.h" #include "string-util.h" @@ -87,54 +89,69 @@ static int parse_argv(int argc, char *argv[]) { static int emit_deprecation_warning(void) { _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; - _cleanup_free_ char *unit = NULL, *unit_path = NULL; - _cleanup_strv_free_ char **a = NULL, **b = NULL; + _cleanup_strv_free_ char **a = NULL; + _cleanup_free_ char *unit = NULL; int r; r = sd_pid_get_unit(0, &unit); - if (r < 0 || !streq(unit, "systemd-udev-settle.service")) + if (r < 0) { + log_debug_errno(r, "Failed to determine unit we run in, ignoring: %m"); + return 0; + } + + if (!streq(unit, "systemd-udev-settle.service")) return 0; - log_notice("systemd-udev-settle.service is deprecated."); - - r = sd_bus_open_system(&bus); + r = bus_connect_system_systemd(&bus); if (r < 0) - return log_debug_errno(r, "Failed to open system bus, skipping dependency queries: %m"); + log_debug_errno(r, "Failed to open connection to systemd, skipping dependency queries: %m"); + else { + _cleanup_strv_free_ char **b = NULL; + _cleanup_free_ char *unit_path = NULL; - unit_path = unit_dbus_path_from_name("systemd-udev-settle.service"); - if (!unit_path) - return -ENOMEM; + unit_path = unit_dbus_path_from_name("systemd-udev-settle.service"); + if (!unit_path) + return -ENOMEM; - (void) sd_bus_get_property_strv( - bus, - "org.freedesktop.systemd1", - unit_path, - "org.freedesktop.systemd1.Unit", - "WantedBy", - NULL, - &a); + (void) sd_bus_get_property_strv( + bus, + "org.freedesktop.systemd1", + unit_path, + "org.freedesktop.systemd1.Unit", + "WantedBy", + NULL, + &a); - (void) sd_bus_get_property_strv( - bus, - "org.freedesktop.systemd1", - unit_path, - "org.freedesktop.systemd1.Unit", - "RequiredBy", - NULL, - &b); + (void) sd_bus_get_property_strv( + bus, + "org.freedesktop.systemd1", + unit_path, + "org.freedesktop.systemd1.Unit", + "RequiredBy", + NULL, + &b); - r = strv_extend_strv(&a, b, true); - if (r < 0) - return r; + r = strv_extend_strv(&a, b, true); + if (r < 0) + return r; + } - if (!strv_isempty(a)) { + if (strv_isempty(a)) + /* Print a simple message if we cannot determine the dependencies */ + log_notice("systemd-udev-settle.service is deprecated."); + else { + /* Print a longer, structured message if we can acquire the dependencies (this should be the + * common case). This is hooked up with a catalog entry and everything. */ _cleanup_free_ char *t = NULL; t = strv_join(a, ", "); if (!t) return -ENOMEM; - log_notice("Hint: please fix %s not to pull it in.", t); + log_struct(LOG_NOTICE, + "MESSAGE=systemd-udev-settle.service is deprecated. Please fix %s not to pull it in.", t, + "OFFENDING_UNITS=%s", t, + "MESSAGE_ID=" SD_MESSAGE_SYSTEMD_UDEV_SETTLE_DEPRECATED_STR); } return 0;