summaryrefslogtreecommitdiff
path: root/src/udev/udevd.c
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2022-07-13 11:52:37 +0900
committerYu Watanabe <watanabe.yu+github@gmail.com>2022-07-23 15:05:22 +0900
commite9d1fae3bbf4e4ee6a5416f8ed0e498f034f4d98 (patch)
treec4f6a22e2b256585dc1cf6fc9f643a61c3a999b7 /src/udev/udevd.c
parentacfbd71ccc3c316c335accfb872937cbf9d3dde3 (diff)
downloadsystemd-e9d1fae3bbf4e4ee6a5416f8ed0e498f034f4d98.tar.gz
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.
Diffstat (limited to 'src/udev/udevd.c')
-rw-r--r--src/udev/udevd.c58
1 files changed, 31 insertions, 27 deletions
diff --git a/src/udev/udevd.c b/src/udev/udevd.c
index a457ebcc9a..0a68b7e6ac 100644
--- a/src/udev/udevd.c
+++ b/src/udev/udevd.c
@@ -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);