1
0
mirror of https://github.com/systemd/systemd.git synced 2025-01-03 05:18:09 +03:00

udev: support reloading udev.conf (#35458)

This makes systemd-udevd reload udev.conf when explicitly requested by
e.g. `udevadm control --reload`.
This commit is contained in:
Yu Watanabe 2024-12-20 09:00:48 +09:00 committed by GitHub
commit 3b9010b170
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 87 additions and 18 deletions

View File

@ -42,11 +42,28 @@ void udev_builtin_exit(void) {
(*b)->exit();
}
bool udev_builtin_should_reload(void) {
UdevReloadFlags udev_builtin_should_reload(void) {
UdevReloadFlags flags = 0;
for (UdevBuiltinCommand i = 0; i < _UDEV_BUILTIN_MAX; i++)
if (builtins[i] && builtins[i]->should_reload && builtins[i]->should_reload())
return true;
return false;
flags |= 1u << i;
if (flags != 0)
flags |= UDEV_RELOAD_KILL_WORKERS;
return flags;
}
void udev_builtin_reload(UdevReloadFlags flags) {
for (UdevBuiltinCommand i = 0; i < _UDEV_BUILTIN_MAX; i++) {
if (!FLAGS_SET(flags, 1u << i) || !builtins[i])
continue;
if (builtins[i]->exit)
builtins[i]->exit();
if (builtins[i]->init)
builtins[i]->init();
}
}
void udev_builtin_list(void) {

View File

@ -59,7 +59,8 @@ const char* udev_builtin_name(UdevBuiltinCommand cmd);
bool udev_builtin_run_once(UdevBuiltinCommand cmd);
int udev_builtin_run(UdevEvent *event, UdevBuiltinCommand cmd, const char *command);
void udev_builtin_list(void);
bool udev_builtin_should_reload(void);
UdevReloadFlags udev_builtin_should_reload(void);
void udev_builtin_reload(UdevReloadFlags flags);
int udev_builtin_add_property(UdevEvent *event, const char *key, const char *val);
int udev_builtin_add_propertyf(UdevEvent *event, const char *key, const char *valf, ...) _printf_(3, 4);
int udev_builtin_import_property(UdevEvent *event, const char *key);

View File

@ -339,3 +339,27 @@ int manager_load(Manager *manager, int argc, char *argv[]) {
manager_adjust_config(&manager->config);
return 1;
}
UdevReloadFlags manager_reload_config(Manager *manager) {
assert(manager);
UdevConfig old = manager->config;
manager->config_by_udev_conf = UDEV_CONFIG_INIT;
manager_parse_udev_config(&manager->config_by_udev_conf);
manager_merge_config(manager);
log_set_max_level(manager->config.log_level);
manager_adjust_config(&manager->config);
if (manager->config.resolve_name_timing != old.resolve_name_timing)
return UDEV_RELOAD_RULES | UDEV_RELOAD_KILL_WORKERS;
if (manager->config.log_level != old.log_level ||
manager->config.exec_delay_usec != old.exec_delay_usec ||
manager->config.timeout_usec != old.timeout_usec ||
manager->config.timeout_signal != old.timeout_signal ||
manager->config.blockdev_read_only != old.blockdev_read_only)
return UDEV_RELOAD_KILL_WORKERS;
return 0;
}

View File

@ -27,4 +27,5 @@ typedef struct UdevConfig {
}
int manager_load(Manager *manager, int argc, char *argv[]);
UdevReloadFlags manager_reload_config(Manager *manager);
void udev_config_set_default_children_max(UdevConfig *c);

View File

@ -55,3 +55,26 @@ typedef enum UdevBuiltinCommand {
_UDEV_BUILTIN_MAX,
_UDEV_BUILTIN_INVALID = -EINVAL,
} UdevBuiltinCommand;
typedef enum UdevReloadFlags {
#if HAVE_BLKID
UDEV_RELOAD_BUILTIN_BLKID = 1u << UDEV_BUILTIN_BLKID,
#endif
UDEV_RELOAD_BUILTIN_BTRFS = 1u << UDEV_BUILTIN_BTRFS,
UDEV_RELOAD_BUILTIN_HWDB = 1u << UDEV_BUILTIN_HWDB,
UDEV_RELOAD_BUILTIN_INPUT_ID = 1u << UDEV_BUILTIN_INPUT_ID,
UDEV_RELOAD_BUILTIN_KEYBOARD = 1u << UDEV_BUILTIN_KEYBOARD,
#if HAVE_KMOD
UDEV_RELOAD_BUILTIN_KMOD = 1u << UDEV_BUILTIN_KMOD,
#endif
UDEV_RELOAD_BUILTIN_DRIVER = 1u << UDEV_BUILTIN_NET_DRIVER,
UDEV_RELOAD_BUILTIN_NET_ID = 1u << UDEV_BUILTIN_NET_ID,
UDEV_RELOAD_BUILTIN_NET_LINK = 1u << UDEV_BUILTIN_NET_LINK,
UDEV_RELOAD_BUILTIN_PATH_ID = 1u << UDEV_BUILTIN_PATH_ID,
UDEV_RELOAD_BUILTIN_USB_ID = 1u << UDEV_BUILTIN_USB_ID,
#if HAVE_ACL
UDEV_RELOAD_BUILTIN_UACCESS = 1u << UDEV_BUILTIN_UACCESS,
#endif
UDEV_RELOAD_KILL_WORKERS = 1u << (_UDEV_BUILTIN_MAX + 0),
UDEV_RELOAD_RULES = 1u << (_UDEV_BUILTIN_MAX + 1),
} UdevReloadFlags;

View File

@ -262,22 +262,25 @@ static void manager_reload(Manager *manager, bool force) {
/* Reload SELinux label database, to make the child inherit the up-to-date database. */
mac_selinux_maybe_reload();
/* Nothing changed. It is not necessary to reload. */
if (!udev_rules_should_reload(manager->rules) && !udev_builtin_should_reload()) {
if (!force)
UdevReloadFlags flags = udev_builtin_should_reload();
if (udev_rules_should_reload(manager->rules))
flags |= UDEV_RELOAD_RULES | UDEV_RELOAD_KILL_WORKERS;
if (flags == 0 && !force)
/* Neither .rules files nor config files for builtins e.g. .link files changed. It is not
* necessary to reload configs. Note, udev.conf is not checked in the above, hence reloaded
* when explicitly requested or at least one .rules file or friend is updated. */
return;
/* If we eat this up, then tell our service manager to just continue */
(void) notify_reloading_full("Skipping configuration reloading, nothing changed.");
} else {
(void) notify_reloading();
flags |= manager_reload_config(manager);
if (FLAGS_SET(flags, UDEV_RELOAD_KILL_WORKERS))
manager_kill_workers(manager, false);
udev_builtin_exit();
udev_builtin_init();
udev_builtin_reload(flags);
if (FLAGS_SET(flags, UDEV_RELOAD_RULES)) {
r = udev_rules_load(&rules, manager->config.resolve_name_timing);
if (r < 0)
log_warning_errno(r, "Failed to read udev rules, using the previously loaded rules, ignoring: %m");

View File

@ -27,7 +27,7 @@ event_timeout=10
timeout_signal=SIGABRT
EOF
systemctl restart systemd-udevd.service
systemctl reload systemd-udevd.service
}
# shellcheck disable=SC2317
@ -40,7 +40,7 @@ teardown() {
rm -rf "$TMPDIR"
rm -f "$TEST_RULE" "$TEST_CONF"
systemctl restart systemd-udevd.service
systemctl reload systemd-udevd.service
}
run_test_timeout() {

View File

@ -18,7 +18,7 @@ at_exit() {
# Forcibly kills sleep command invoked by the udev rule before restarting,
# otherwise systemctl restart below will takes longer.
killall -KILL sleep
systemctl restart systemd-udevd.service
udevadm control --reload
ip link del "$IFNAME"
}
@ -36,7 +36,7 @@ cat >/run/udev/rules.d/99-testsuite.rules <<EOF
SUBSYSTEM=="net", ACTION=="change", KERNEL=="${IFNAME}", OPTIONS="log_level=debug", RUN+="/usr/bin/sleep 1000"
EOF
systemctl restart systemd-udevd.service
udevadm control --reload
ip link add "$IFNAME" type dummy
IFINDEX=$(ip -json link show "$IFNAME" | jq '.[].ifindex')