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.
This commit is contained in:
Lennart Poettering 2020-07-08 17:51:55 +02:00 committed by Zbigniew Jędrzejewski-Szmek
parent a18c7865be
commit 77ee1783eb
3 changed files with 86 additions and 31 deletions

View File

@ -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@

View File

@ -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

View File

@ -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;