udev: several trivial cleanups ()

This commit is contained in:
Luca Boccassi 2025-04-09 10:32:42 +01:00 committed by GitHub
commit 4dca06cba9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 223 additions and 235 deletions

View File

@ -110,7 +110,7 @@ _udevadm() {
)
local verbs=(info trigger settle control monitor test-builtin test verify cat wait lock)
local builtins=(blkid btrfs factory_reset hwdb input_id keyboard kmod net_driver net_id net_setup_link path_id uaccess usb_id)
local builtins=(blkid btrfs dissect_image factory_reset hwdb input_id keyboard kmod net_driver net_id net_setup_link path_id uaccess usb_id)
for ((i=0; i < COMP_CWORD; i++)); do
if __contains_word "${COMP_WORDS[i]}" "${verbs[@]}"; then

View File

@ -103,7 +103,7 @@ _udevadm_test-builtin(){
'(- *)'{-h,--help}'[Print help]' \
'(- *)'{-V,--version}'[Print version of the program]' \
'--action=[The action string.]:actions:(add change remove move online offline bind unbind)' \
'*::builtins:(blkid btrfs factory_reset hwdb input_id keyboard kmod net_driver net_id net_setup_link path_id uaccess usb_id)'
'*::builtins:(blkid btrfs dissect_image factory_reset hwdb input_id keyboard kmod net_driver net_id net_setup_link path_id uaccess usb_id)'
elif (( CURRENT == 3 )); then
_arguments \
'--action=[The action string.]:actions:(add change remove move online offline bind unbind)' \

View File

@ -20,6 +20,7 @@
#define WORKER_NUM_MAX UINT64_C(2048)
static int default_log_level = LOG_INFO;
static bool arg_debug = false;
bool arg_daemonize = false;
@ -279,7 +280,7 @@ static void manager_merge_config_log_level(Manager *manager) {
if (manager->config.trace)
manager->config.log_level = LOG_DEBUG;
else
MERGE_NON_NEGATIVE(log_level, log_get_max_level());
MERGE_NON_NEGATIVE(log_level, default_log_level);
}
static void manager_merge_config(Manager *manager) {
@ -441,6 +442,8 @@ int manager_load(Manager *manager, int argc, char *argv[]) {
assert(manager);
default_log_level = log_get_max_level();
manager_parse_udev_config(&manager->config_by_udev_conf);
r = parse_argv(argc, argv, &manager->config_by_command);

View File

@ -160,47 +160,23 @@ Manager* manager_free(Manager *manager) {
return mfree(manager);
}
static int on_sigchld(sd_event_source *s, const siginfo_t *si, void *userdata);
Manager* manager_new(void) {
Manager *manager;
static int worker_new(Worker **ret, Manager *manager, sd_device_monitor *worker_monitor, PidRef *pidref) {
_cleanup_(worker_freep) Worker *worker = NULL;
int r;
manager = new(Manager, 1);
if (!manager)
return NULL;
assert(ret);
assert(manager);
assert(worker_monitor);
assert(pidref);
/* This takes and invalidates pidref even on some error cases. */
worker = new(Worker, 1);
if (!worker)
return -ENOMEM;
*worker = (Worker) {
.pidref = TAKE_PIDREF(*pidref),
*manager = (Manager) {
.inotify_fd = -EBADF,
.config_by_udev_conf = UDEV_CONFIG_INIT,
.config_by_command = UDEV_CONFIG_INIT,
.config_by_kernel = UDEV_CONFIG_INIT,
.config_by_control = UDEV_CONFIG_INIT,
.config = UDEV_CONFIG_INIT,
};
r = device_monitor_get_address(worker_monitor, &worker->address);
if (r < 0)
return r;
r = event_add_child_pidref(manager->event, &worker->child_event_source, &worker->pidref, WEXITED, on_sigchld, worker);
if (r < 0)
return r;
r = sd_event_source_set_priority(worker->child_event_source, EVENT_PRIORITY_WORKER_SIGCHLD);
if (r < 0)
return r;
r = hashmap_ensure_put(&manager->workers, &worker_hash_op, &worker->pidref, worker);
if (r < 0)
return r;
worker->manager = manager;
*ret = TAKE_PTR(worker);
return 0;
return manager;
}
void manager_kill_workers(Manager *manager, int signo) {
@ -335,6 +311,94 @@ void manager_reload(Manager *manager, bool force) {
notify_ready(manager);
}
static int on_sigchld(sd_event_source *s, const siginfo_t *si, void *userdata) {
_cleanup_(worker_freep) Worker *worker = ASSERT_PTR(userdata);
sd_device *dev = worker->event ? ASSERT_PTR(worker->event->dev) : NULL;
int r;
assert(si);
switch (si->si_code) {
case CLD_EXITED:
if (si->si_status == 0) {
log_device_debug(dev, "Worker ["PID_FMT"] exited.", si->si_pid);
return 0;
}
log_device_warning(dev, "Worker ["PID_FMT"] exited with return code %i.",
si->si_pid, si->si_status);
if (!dev)
return 0;
(void) device_add_exit_status(dev, si->si_status);
break;
case CLD_KILLED:
case CLD_DUMPED:
log_device_warning(dev, "Worker ["PID_FMT"] terminated by signal %i (%s).",
si->si_pid, si->si_status, signal_to_string(si->si_status));
if (!dev)
return 0;
(void) device_add_signal(dev, si->si_status);
break;
default:
assert_not_reached();
}
/* delete state from disk */
device_delete_db(dev);
device_tag_index(dev, NULL, false);
r = device_monitor_send(worker->manager->monitor, NULL, dev);
if (r < 0)
log_device_warning_errno(dev, r, "Failed to broadcast event to libudev listeners, ignoring: %m");
return 0;
}
static int worker_new(Worker **ret, Manager *manager, sd_device_monitor *worker_monitor, PidRef *pidref) {
_cleanup_(worker_freep) Worker *worker = NULL;
int r;
assert(ret);
assert(manager);
assert(worker_monitor);
assert(pidref);
/* This takes and invalidates pidref even on some error cases. */
worker = new(Worker, 1);
if (!worker)
return -ENOMEM;
*worker = (Worker) {
.pidref = TAKE_PIDREF(*pidref),
};
r = device_monitor_get_address(worker_monitor, &worker->address);
if (r < 0)
return r;
r = event_add_child_pidref(manager->event, &worker->child_event_source, &worker->pidref, WEXITED, on_sigchld, worker);
if (r < 0)
return r;
r = sd_event_source_set_priority(worker->child_event_source, EVENT_PRIORITY_WORKER_SIGCHLD);
if (r < 0)
return r;
r = hashmap_ensure_put(&manager->workers, &worker_hash_op, &worker->pidref, worker);
if (r < 0)
return r;
worker->manager = manager;
*ret = TAKE_PTR(worker);
return 0;
}
static int on_event_timeout(sd_event_source *s, uint64_t usec, void *userdata) {
Event *event = ASSERT_PTR(userdata);
@ -806,6 +870,60 @@ static int on_uevent(sd_device_monitor *monitor, sd_device *dev, void *userdata)
return 1;
}
static int manager_init_device_monitor(Manager *manager, int fd) {
int r;
assert(manager);
/* This takes passed file descriptor on success. */
if (fd >= 0) {
if (manager->monitor)
return log_warning_errno(SYNTHETIC_ERRNO(EALREADY), "Received multiple netlink socket (%i), ignoring.", fd);
r = sd_is_socket(fd, AF_NETLINK, SOCK_RAW, /* listening = */ -1);
if (r < 0)
return log_warning_errno(r, "Failed to verify socket type of %i, ignoring: %m", fd);
if (r == 0)
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), "Received invalid netlink socket (%i), ignoring.", fd);
} else {
if (manager->monitor)
return 0;
}
r = device_monitor_new_full(&manager->monitor, MONITOR_GROUP_KERNEL, fd);
if (r < 0)
return log_error_errno(r, "Failed to initialize device monitor: %m");
return 0;
}
static int manager_start_device_monitor(Manager *manager) {
int r;
assert(manager);
r = manager_init_device_monitor(manager, -EBADF);
if (r < 0)
return r;
(void) sd_device_monitor_set_description(manager->monitor, "manager");
r = sd_device_monitor_attach_event(manager->monitor, manager->event);
if (r < 0)
return log_error_errno(r, "Failed to attach event to device monitor: %m");
r = sd_device_monitor_start(manager->monitor, on_uevent, manager);
if (r < 0)
return log_error_errno(r, "Failed to start device monitor: %m");
r = sd_event_source_set_priority(sd_device_monitor_get_event_source(manager->monitor), EVENT_PRIORITY_DEVICE_MONITOR);
if (r < 0)
return log_error_errno(r, "Failed to set priority to device monitor: %m");
return 0;
}
static int on_worker_notify(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
Manager *manager = ASSERT_PTR(userdata);
int r;
@ -882,6 +1000,24 @@ static int on_worker_notify(sd_event_source *s, int fd, uint32_t revents, void *
return 0;
}
static int manager_start_worker_notify(Manager *manager) {
int r;
assert(manager);
assert(manager->event);
r = notify_socket_prepare(
manager->event,
EVENT_PRIORITY_WORKER_NOTIFY,
on_worker_notify,
manager,
&manager->worker_notify_socket_path);
if (r < 0)
return log_error_errno(r, "Failed to prepare worker notification socket: %m");
return 0;
}
static int on_sigterm(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
Manager *manager = ASSERT_PTR(userdata);
@ -898,53 +1034,6 @@ static int on_sighup(sd_event_source *s, const struct signalfd_siginfo *si, void
return 1;
}
static int on_sigchld(sd_event_source *s, const siginfo_t *si, void *userdata) {
_cleanup_(worker_freep) Worker *worker = ASSERT_PTR(userdata);
sd_device *dev = worker->event ? ASSERT_PTR(worker->event->dev) : NULL;
int r;
assert(si);
switch (si->si_code) {
case CLD_EXITED:
if (si->si_status == 0) {
log_device_debug(dev, "Worker ["PID_FMT"] exited.", si->si_pid);
return 0;
}
log_device_warning(dev, "Worker ["PID_FMT"] exited with return code %i.",
si->si_pid, si->si_status);
if (!dev)
return 0;
(void) device_add_exit_status(dev, si->si_status);
break;
case CLD_KILLED:
case CLD_DUMPED:
log_device_warning(dev, "Worker ["PID_FMT"] terminated by signal %i (%s).",
si->si_pid, si->si_status, signal_to_string(si->si_status));
if (!dev)
return 0;
(void) device_add_signal(dev, si->si_status);
break;
default:
assert_not_reached();
}
/* delete state from disk */
device_delete_db(dev);
device_tag_index(dev, NULL, false);
r = device_monitor_send(worker->manager->monitor, NULL, dev);
if (r < 0)
log_device_warning_errno(dev, r, "Failed to broadcast event to libudev listeners, ignoring: %m");
return 0;
}
static int manager_unlink_queue_file(Manager *manager) {
assert(manager);
@ -1009,149 +1098,6 @@ static int on_post(sd_event_source *s, void *userdata) {
return 0;
}
Manager* manager_new(void) {
Manager *manager;
manager = new(Manager, 1);
if (!manager)
return NULL;
*manager = (Manager) {
.inotify_fd = -EBADF,
.config_by_udev_conf = UDEV_CONFIG_INIT,
.config_by_command = UDEV_CONFIG_INIT,
.config_by_kernel = UDEV_CONFIG_INIT,
.config_by_control = UDEV_CONFIG_INIT,
.config = UDEV_CONFIG_INIT,
};
return manager;
}
static int manager_init_device_monitor(Manager *manager, int fd) {
int r;
assert(manager);
/* This takes passed file descriptor on success. */
if (fd >= 0) {
if (manager->monitor)
return log_warning_errno(SYNTHETIC_ERRNO(EALREADY), "Received multiple netlink socket (%i), ignoring.", fd);
r = sd_is_socket(fd, AF_NETLINK, SOCK_RAW, /* listening = */ -1);
if (r < 0)
return log_warning_errno(r, "Failed to verify socket type of %i, ignoring: %m", fd);
if (r == 0)
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), "Received invalid netlink socket (%i), ignoring.", fd);
} else {
if (manager->monitor)
return 0;
}
r = device_monitor_new_full(&manager->monitor, MONITOR_GROUP_KERNEL, fd);
if (r < 0)
return log_error_errno(r, "Failed to initialize device monitor: %m");
return 0;
}
static int manager_listen_fds(Manager *manager) {
_cleanup_strv_free_ char **names = NULL;
int r;
assert(manager);
int n = sd_listen_fds_with_names(/* unset_environment = */ true, &names);
if (n < 0)
return n;
for (int i = 0; i < n; i++) {
int fd = SD_LISTEN_FDS_START + i;
if (streq(names[i], "varlink"))
r = 0; /* The fd will be handled by sd_varlink_server_listen_auto(). */
else if (streq(names[i], "systemd-udevd-control.socket"))
r = manager_init_ctrl(manager, fd);
else if (streq(names[i], "systemd-udevd-kernel.socket"))
r = manager_init_device_monitor(manager, fd);
else if (streq(names[i], "inotify"))
r = manager_init_inotify(manager, fd);
else
r = log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
"Received unexpected fd (%s), ignoring.", names[i]);
if (r < 0)
close_and_notify_warn(fd, names[i]);
}
return 0;
}
int manager_init(Manager *manager) {
int r;
assert(manager);
r = manager_listen_fds(manager);
if (r < 0)
return log_error_errno(r, "Failed to listen on fds: %m");
_cleanup_free_ char *cgroup = NULL;
r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 0, &cgroup);
if (r < 0)
log_debug_errno(r, "Failed to get cgroup, ignoring: %m");
else if (endswith(cgroup, "/udev")) { /* If we are in a subcgroup /udev/ we assume it was delegated to us */
log_debug("Running in delegated subcgroup '%s'.", cgroup);
manager->cgroup = TAKE_PTR(cgroup);
}
return 0;
}
static int manager_start_device_monitor(Manager *manager) {
int r;
assert(manager);
r = manager_init_device_monitor(manager, -EBADF);
if (r < 0)
return r;
(void) sd_device_monitor_set_description(manager->monitor, "manager");
r = sd_device_monitor_attach_event(manager->monitor, manager->event);
if (r < 0)
return log_error_errno(r, "Failed to attach event to device monitor: %m");
r = sd_device_monitor_start(manager->monitor, on_uevent, manager);
if (r < 0)
return log_error_errno(r, "Failed to start device monitor: %m");
r = sd_event_source_set_priority(sd_device_monitor_get_event_source(manager->monitor), EVENT_PRIORITY_DEVICE_MONITOR);
if (r < 0)
return log_error_errno(r, "Failed to set priority to device monitor: %m");
return 0;
}
static int manager_start_worker_notify(Manager *manager) {
int r;
assert(manager);
assert(manager->event);
r = notify_socket_prepare(
manager->event,
EVENT_PRIORITY_WORKER_NOTIFY,
on_worker_notify,
manager,
&manager->worker_notify_socket_path);
if (r < 0)
return log_error_errno(r, "Failed to prepare worker notification socket: %m");
return 0;
}
static int manager_setup_event(Manager *manager) {
_cleanup_(sd_event_unrefp) sd_event *e = NULL;
int r;
@ -1200,15 +1146,59 @@ static int manager_setup_event(Manager *manager) {
return 0;
}
static int manager_listen_fds(Manager *manager) {
_cleanup_strv_free_ char **names = NULL;
int r;
assert(manager);
int n = sd_listen_fds_with_names(/* unset_environment = */ true, &names);
if (n < 0)
return n;
for (int i = 0; i < n; i++) {
int fd = SD_LISTEN_FDS_START + i;
if (streq(names[i], "varlink"))
r = 0; /* The fd will be handled by sd_varlink_server_listen_auto(). */
else if (streq(names[i], "systemd-udevd-control.socket"))
r = manager_init_ctrl(manager, fd);
else if (streq(names[i], "systemd-udevd-kernel.socket"))
r = manager_init_device_monitor(manager, fd);
else if (streq(names[i], "inotify"))
r = manager_init_inotify(manager, fd);
else
r = log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
"Received unexpected fd (%s), ignoring.", names[i]);
if (r < 0)
close_and_notify_warn(fd, names[i]);
}
return 0;
}
int manager_main(Manager *manager) {
int r;
assert(manager);
_cleanup_free_ char *cgroup = NULL;
r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 0, &cgroup);
if (r < 0)
log_debug_errno(r, "Failed to get cgroup, ignoring: %m");
else if (endswith(cgroup, "/udev")) { /* If we are in a subcgroup /udev/ we assume it was delegated to us */
log_debug("Running in delegated subcgroup '%s'.", cgroup);
manager->cgroup = TAKE_PTR(cgroup);
}
r = manager_setup_event(manager);
if (r < 0)
return r;
r = manager_listen_fds(manager);
if (r < 0)
return r;
r = manager_start_ctrl(manager);
if (r < 0)
return r;

View File

@ -68,7 +68,6 @@ Manager* manager_new(void);
Manager* manager_free(Manager *manager);
DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free);
int manager_init(Manager *manager);
int manager_main(Manager *manager);
void manager_reload(Manager *manager, bool force);
void manager_exit(Manager *manager);

View File

@ -51,10 +51,6 @@ int run_udevd(int argc, char *argv[]) {
if (r < 0 && r != -EEXIST)
return log_error_errno(r, "Failed to create /run/udev: %m");
r = manager_init(manager);
if (r < 0)
return r;
if (arg_daemonize) {
pid_t pid;