mirror of
https://github.com/systemd/systemd.git
synced 2026-08-03 14:40:31 +00:00
udev: save stats of all udev rules file
The mtime of directory is not updated when an existing rule file is changed. Hence, paths_check_timestamp() is not reliable.
This commit is contained in:
@@ -445,7 +445,7 @@ int config_parse(
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int hashmap_put_stats_by_path(Hashmap **stats_by_path, const char *path, const struct stat *st) {
|
||||
int hashmap_put_stats_by_path(Hashmap **stats_by_path, const char *path, const struct stat *st) {
|
||||
_cleanup_free_ struct stat *st_copy = NULL;
|
||||
_cleanup_free_ char *path_copy = NULL;
|
||||
int r;
|
||||
|
||||
@@ -122,6 +122,7 @@ int config_get_stats_by_path(
|
||||
bool check_dropins,
|
||||
Hashmap **ret);
|
||||
|
||||
int hashmap_put_stats_by_path(Hashmap **stats_by_path, const char *path, const struct stat *st);
|
||||
bool stats_by_path_equal(Hashmap *a, Hashmap *b);
|
||||
|
||||
typedef struct ConfigSection {
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "alloc-util.h"
|
||||
#include "architecture.h"
|
||||
#include "conf-files.h"
|
||||
#include "conf-parser.h"
|
||||
#include "def.h"
|
||||
#include "device-private.h"
|
||||
#include "device-util.h"
|
||||
@@ -177,10 +178,10 @@ struct UdevRuleFile {
|
||||
};
|
||||
|
||||
struct UdevRules {
|
||||
usec_t dirs_ts_usec;
|
||||
ResolveNameTiming resolve_name_timing;
|
||||
Hashmap *known_users;
|
||||
Hashmap *known_groups;
|
||||
Hashmap *stats_by_path;
|
||||
UdevRuleFile *current_file;
|
||||
LIST_HEAD(UdevRuleFile, rule_files);
|
||||
};
|
||||
@@ -315,6 +316,7 @@ UdevRules *udev_rules_free(UdevRules *rules) {
|
||||
|
||||
hashmap_free_free_key(rules->known_users);
|
||||
hashmap_free_free_key(rules->known_groups);
|
||||
hashmap_free(rules->stats_by_path);
|
||||
return mfree(rules);
|
||||
}
|
||||
|
||||
@@ -1176,6 +1178,7 @@ int udev_rules_parse_file(UdevRules *rules, const char *filename) {
|
||||
UdevRuleFile *rule_file;
|
||||
bool ignore_line = false;
|
||||
unsigned line_nr = 0;
|
||||
struct stat st;
|
||||
int r;
|
||||
|
||||
f = fopen(filename, "re");
|
||||
@@ -1183,16 +1186,23 @@ int udev_rules_parse_file(UdevRules *rules, const char *filename) {
|
||||
if (errno == ENOENT)
|
||||
return 0;
|
||||
|
||||
return -errno;
|
||||
return log_warning_errno(errno, "Failed to open %s, ignoring: %m", filename);
|
||||
}
|
||||
|
||||
(void) fd_warn_permissions(filename, fileno(f));
|
||||
if (fstat(fileno(f), &st) < 0)
|
||||
return log_warning_errno(errno, "Failed to stat %s, ignoring: %m", filename);
|
||||
|
||||
if (null_or_empty_fd(fileno(f))) {
|
||||
if (null_or_empty(&st)) {
|
||||
log_debug("Skipping empty file: %s", filename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = hashmap_put_stats_by_path(&rules->stats_by_path, filename, &st);
|
||||
if (r < 0)
|
||||
return log_warning_errno(errno, "Failed to save stat for %s, ignoring: %m", filename);
|
||||
|
||||
(void) fd_warn_permissions(filename, fileno(f));
|
||||
|
||||
log_debug("Reading rules file: %s", filename);
|
||||
|
||||
name = strdup(filename);
|
||||
@@ -1296,8 +1306,6 @@ int udev_rules_load(UdevRules **ret_rules, ResolveNameTiming resolve_name_timing
|
||||
if (!rules)
|
||||
return -ENOMEM;
|
||||
|
||||
(void) udev_rules_check_timestamp(rules);
|
||||
|
||||
r = conf_files_list_strv(&files, ".rules", NULL, 0, RULES_DIRS);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to enumerate rules files: %m");
|
||||
@@ -1312,11 +1320,25 @@ int udev_rules_load(UdevRules **ret_rules, ResolveNameTiming resolve_name_timing
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool udev_rules_check_timestamp(UdevRules *rules) {
|
||||
if (!rules)
|
||||
return false;
|
||||
bool udev_rules_should_reload(UdevRules *rules) {
|
||||
_cleanup_hashmap_free_ Hashmap *stats_by_path = NULL;
|
||||
int r;
|
||||
|
||||
return paths_check_timestamp(RULES_DIRS, &rules->dirs_ts_usec, true);
|
||||
if (!rules)
|
||||
return true;
|
||||
|
||||
r = config_get_stats_by_path(".rules", NULL, 0, RULES_DIRS, /* check_dropins = */ false, &stats_by_path);
|
||||
if (r < 0) {
|
||||
log_warning_errno(r, "Failed to get stats of udev rules, ignoring: %m");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!stats_by_path_equal(rules->stats_by_path, stats_by_path)) {
|
||||
log_debug("Udev rules need reloading");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool token_match_string(UdevRuleToken *token, const char *str) {
|
||||
|
||||
@@ -22,7 +22,7 @@ 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);
|
||||
|
||||
bool udev_rules_check_timestamp(UdevRules *rules);
|
||||
bool udev_rules_should_reload(UdevRules *rules);
|
||||
int udev_rules_apply_to_event(UdevRules *rules, UdevEvent *event,
|
||||
usec_t timeout_usec,
|
||||
int timeout_signal,
|
||||
|
||||
@@ -949,7 +949,7 @@ static int event_queue_start(Manager *manager) {
|
||||
/* 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_check_timestamp(manager->rules) ||
|
||||
if (udev_rules_should_reload(manager->rules) ||
|
||||
udev_builtin_validate())
|
||||
manager_reload(manager);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user