mirror of
https://github.com/Dasharo/systemd.git
synced 2026-03-06 15:02:31 -08:00
udev: reload rules and builtins only when mtime of a config changed
This makes udevd reload rules only when the timestamp is updated, even on SIGHUP or `udevadm control --reload`. So, we can call `udevadm control --reload` without huge performance penalty when no rules, .link files, and so on are changed.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
#pragma once
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "hashmap.h"
|
||||
#include "time-util.h"
|
||||
#include "udev-util.h"
|
||||
@@ -21,6 +22,7 @@ UdevRules* udev_rules_new(ResolveNameTiming resolve_name_timing);
|
||||
int udev_rules_load(UdevRules **ret_rules, ResolveNameTiming resolve_name_timing);
|
||||
UdevRules *udev_rules_free(UdevRules *rules);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(UdevRules*, udev_rules_free);
|
||||
#define udev_rules_free_and_replace(a, b) free_and_replace_full(a, b, udev_rules_free)
|
||||
|
||||
bool udev_rules_should_reload(UdevRules *rules);
|
||||
int udev_rules_apply_to_event(UdevRules *rules, UdevEvent *event,
|
||||
|
||||
@@ -351,16 +351,40 @@ static void notify_ready(void) {
|
||||
}
|
||||
|
||||
/* reload requested, HUP signal received, rules changed, builtin changed */
|
||||
static void manager_reload(Manager *manager) {
|
||||
static void manager_reload(Manager *manager, bool force) {
|
||||
_cleanup_(udev_rules_freep) UdevRules *rules = NULL;
|
||||
usec_t now_usec;
|
||||
int r;
|
||||
|
||||
assert(manager);
|
||||
|
||||
assert_se(sd_event_now(manager->event, CLOCK_MONOTONIC, &now_usec) >= 0);
|
||||
if (!force && now_usec < usec_add(manager->last_usec, 3 * USEC_PER_SEC))
|
||||
/* check for changed config, every 3 seconds at most */
|
||||
return;
|
||||
manager->last_usec = now_usec;
|
||||
|
||||
/* 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_validate())
|
||||
return;
|
||||
|
||||
sd_notify(false,
|
||||
"RELOADING=1\n"
|
||||
"STATUS=Flushing configuration...");
|
||||
|
||||
manager_kill_workers(manager, false);
|
||||
manager->rules = udev_rules_free(manager->rules);
|
||||
|
||||
udev_builtin_exit();
|
||||
udev_builtin_init();
|
||||
|
||||
r = udev_rules_load(&rules, arg_resolve_name_timing);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to read udev rules, using the previously loaded rules, ignoring: %m");
|
||||
else
|
||||
udev_rules_free_and_replace(manager->rules, rules);
|
||||
|
||||
notify_ready();
|
||||
}
|
||||
@@ -937,7 +961,6 @@ no_blocker:
|
||||
}
|
||||
|
||||
static int event_queue_start(Manager *manager) {
|
||||
usec_t usec;
|
||||
int r;
|
||||
|
||||
assert(manager);
|
||||
@@ -945,32 +968,11 @@ static int event_queue_start(Manager *manager) {
|
||||
if (!manager->events || manager->exit || manager->stop_exec_queue)
|
||||
return 0;
|
||||
|
||||
assert_se(sd_event_now(manager->event, CLOCK_MONOTONIC, &usec) >= 0);
|
||||
/* check for changed config, every 3 seconds at most */
|
||||
if (manager->last_usec == 0 ||
|
||||
usec > usec_add(manager->last_usec, 3 * USEC_PER_SEC)) {
|
||||
if (udev_rules_should_reload(manager->rules) ||
|
||||
udev_builtin_validate())
|
||||
manager_reload(manager);
|
||||
|
||||
manager->last_usec = usec;
|
||||
}
|
||||
|
||||
r = event_source_disable(manager->kill_workers_event);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to disable event source for cleaning up idle workers, ignoring: %m");
|
||||
|
||||
udev_builtin_init();
|
||||
|
||||
if (!manager->rules) {
|
||||
r = udev_rules_load(&manager->rules, arg_resolve_name_timing);
|
||||
if (r < 0)
|
||||
return log_warning_errno(r, "Failed to read udev rules: %m");
|
||||
}
|
||||
|
||||
/* fork with up-to-date SELinux label database, so the child inherits the up-to-date db
|
||||
* and, until the next SELinux policy changes, we safe further reloads in future children */
|
||||
mac_selinux_maybe_reload();
|
||||
manager_reload(manager, /* force = */ false);
|
||||
|
||||
LIST_FOREACH(event, event, manager->events) {
|
||||
if (event->state != EVENT_QUEUED)
|
||||
@@ -1252,7 +1254,7 @@ static int on_ctrl_msg(UdevCtrl *uctrl, UdevCtrlMessageType type, const UdevCtrl
|
||||
break;
|
||||
case UDEV_CTRL_RELOAD:
|
||||
log_debug("Received udev control message (RELOAD)");
|
||||
manager_reload(manager);
|
||||
manager_reload(manager, /* force = */ true);
|
||||
break;
|
||||
case UDEV_CTRL_SET_ENV: {
|
||||
_unused_ _cleanup_free_ char *old_val = NULL;
|
||||
@@ -1501,7 +1503,7 @@ static int on_sighup(sd_event_source *s, const struct signalfd_siginfo *si, void
|
||||
|
||||
assert(manager);
|
||||
|
||||
manager_reload(manager);
|
||||
manager_reload(manager, /* force = */ true);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -2011,6 +2013,8 @@ static int main_loop(Manager *manager) {
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to create post event source: %m");
|
||||
|
||||
manager->last_usec = now(CLOCK_MONOTONIC);
|
||||
|
||||
udev_builtin_init();
|
||||
|
||||
r = udev_rules_load(&manager->rules, arg_resolve_name_timing);
|
||||
|
||||
Reference in New Issue
Block a user