udev: reload .rules files and builtins only when necessary

Previously, even if e.g. .rules files are unchanged, all .rules files
are reloaded when other kind of config files like .link files or
.hwdb.bin are changed, vice versa.
This commit is contained in:
Yu Watanabe
2024-12-04 04:31:31 +09:00
parent b5ea69f5ac
commit 0f72af536f
4 changed files with 54 additions and 10 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

@@ -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()) {
UdevReloadFlags flags = udev_builtin_should_reload();
if (udev_rules_should_reload(manager->rules))
flags |= UDEV_RELOAD_RULES | UDEV_RELOAD_KILL_WORKERS;
if (flags == 0) {
/* Nothing changed. It is not necessary to reload. */
if (!force)
return;
/* If we eat this up, then tell our service manager to just continue */
(void) notify_reloading_full("Skipping configuration reloading, nothing changed.");
} else {
} else
(void) notify_reloading();
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");