udevd.c revision f45928521249bbaf5dbea84933ae2fcaf5354080
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering * Copyright (C) 2004-2012 Kay Sievers <kay@vrfy.org>
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering * Copyright (C) 2004 Chris Friesen <chris_friesen@sympatico.ca>
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering * Copyright (C) 2009 Canonical Ltd.
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering * Copyright (C) 2009 Scott James Remnant <scott@netsplit.com>
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering * This program is free software: you can redistribute it and/or modify
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering * it under the terms of the GNU General Public License as published by
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering * the Free Software Foundation, either version 2 of the License, or
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering * (at your option) any later version.
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering * This program is distributed in the hope that it will be useful,
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering * but WITHOUT ANY WARRANTY; without even the implied warranty of
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering * GNU General Public License for more details.
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering * You should have received a copy of the GNU General Public License
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering * along with this program. If not, see <http://www.gnu.org/licenses/>.
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poetteringvoid udev_main_log(struct udev *udev, int priority,
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering const char *file, int line, const char *fn,
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering log_metav(priority, file, line, fn, format, args);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poetteringstatic struct udev_queue_export *udev_queue_export;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering unsigned long long int delaying_seqnum;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering unsigned long long int seqnum;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poetteringstatic inline struct event *node_to_event(struct udev_list_node *node)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return container_of(node, struct event, node);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poetteringstatic void event_queue_cleanup(struct udev *udev, enum event_state type);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering/* passed from worker to main process */
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poetteringstatic inline struct worker *node_to_worker(struct udev_list_node *node)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return container_of(node, struct worker, node);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poetteringstatic void event_queue_delete(struct event *event, bool export)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering udev_queue_export_device_finished(udev_queue_export, event->dev);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering log_debug("seq %llu done with %i\n", udev_device_get_seqnum(event->dev), event->exitcode);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poetteringstatic struct worker *worker_ref(struct worker *worker)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poetteringstatic void worker_cleanup(struct worker *worker)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poetteringstatic void worker_unref(struct worker *worker)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering log_debug("worker [%u] cleaned up\n", worker->pid);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poetteringstatic void worker_list_cleanup(struct udev *udev)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering udev_list_node_foreach_safe(loop, tmp, &worker_list) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering struct worker *worker = node_to_worker(loop);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poetteringstatic void worker_new(struct event *event)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering /* listen for new events */
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering worker_monitor = udev_monitor_new_from_netlink(udev, NULL);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering /* allow the main daemon netlink address to send devices to the worker */
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering udev_monitor_allow_unicast_sender(worker_monitor, monitor);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering udev_monitor_enable_receiving(worker_monitor);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering worker = calloc(1, sizeof(struct worker));
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering /* worker + event reference */
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering struct epoll_event ep_signal, ep_monitor;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering /* take initial device from queue */
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering udev_queue_export_unref(udev_queue_export);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering fd_signal = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering log_error("error creating signalfd %m\n");
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering log_error("error creating epoll fd: %m\n");
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering memset(&ep_signal, 0, sizeof(struct epoll_event));
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering fd_monitor = udev_monitor_get_fd(worker_monitor);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering memset(&ep_monitor, 0, sizeof(struct epoll_event));
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd_signal, &ep_signal) < 0 ||
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd_monitor, &ep_monitor) < 0) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering log_error("fail to add fds to epoll: %m\n");
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering /* request TERM signal if parent exits */
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering /* reset OOM score, we only protect the main daemon */
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering write_one_line_file("/proc/self/oom_score_adj", "0");
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering log_debug("seq %llu running\n", udev_device_get_seqnum(dev));
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering /* needed for SIGCHLD/SIGTERM in spawn() */
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering /* apply rules, create node, symlinks */
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering err = udev_event_execute_rules(udev_event, rules, &sigmask_orig);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering udev_event_execute_run(udev_event, &sigmask_orig);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering /* apply/restore inotify watch */
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (err == 0 && udev_event->inotify_watch) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering /* send processed event back to libudev listeners */
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering udev_monitor_send_device(worker_monitor, NULL, dev);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering /* send udevd the result of the event execution */
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering memset(&msg, 0, sizeof(struct worker_message));
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering send(worker_watch[WRITE_END], &msg, sizeof(struct worker_message), 0);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering log_debug("seq %llu processed with %i\n", udev_device_get_seqnum(dev), err);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering /* wait for more device messages from main udevd, or term signal */
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering fdcount = epoll_wait(fd_ep, ev, ELEMENTSOF(ev), -1);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering for (i = 0; i < fdcount; i++) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (ev[i].data.fd == fd_monitor && ev[i].events & EPOLLIN) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering dev = udev_monitor_receive_device(worker_monitor);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering } else if (ev[i].data.fd == fd_signal && ev[i].events & EPOLLIN) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering size = read(fd_signal, &fdsi, sizeof(struct signalfd_siginfo));
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (size != sizeof(struct signalfd_siginfo))
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering /* close monitor, but keep address around */
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering worker->event_start_usec = now(CLOCK_MONOTONIC);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering udev_list_node_append(&worker->node, &worker_list);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering log_debug("seq %llu forked new worker [%u]\n", udev_device_get_seqnum(event->dev), pid);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poetteringstatic void event_run(struct event *event)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering udev_list_node_foreach(loop, &worker_list) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering struct worker *worker = node_to_worker(loop);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering count = udev_monitor_send_device(monitor, worker->monitor, event->dev);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering log_error("worker [%u] did not accept message %zi (%m), kill it\n", worker->pid, count);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering worker->event_start_usec = now(CLOCK_MONOTONIC);
0193ad26ba121f3df259cc8b3bab54a99b8e5252Cristian RodrÃguez log_debug("maximum number (%i) of children reached\n", children);
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering /* start new worker and pass initial device */
0193ad26ba121f3df259cc8b3bab54a99b8e5252Cristian RodrÃguezstatic int event_queue_insert(struct udev_device *dev)
0193ad26ba121f3df259cc8b3bab54a99b8e5252Cristian RodrÃguez event = calloc(1, sizeof(struct event));
0193ad26ba121f3df259cc8b3bab54a99b8e5252Cristian RodrÃguez event->udev = udev_device_get_udev(dev);
0193ad26ba121f3df259cc8b3bab54a99b8e5252Cristian RodrÃguez event->seqnum = udev_device_get_seqnum(dev);
0193ad26ba121f3df259cc8b3bab54a99b8e5252Cristian RodrÃguez event->devpath = udev_device_get_devpath(dev);
0193ad26ba121f3df259cc8b3bab54a99b8e5252Cristian RodrÃguez event->devpath_len = strlen(event->devpath);
0193ad26ba121f3df259cc8b3bab54a99b8e5252Cristian RodrÃguez event->devpath_old = udev_device_get_devpath_old(dev);
0193ad26ba121f3df259cc8b3bab54a99b8e5252Cristian RodrÃguez event->devnum = udev_device_get_devnum(dev);
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering event->is_block = streq("block", udev_device_get_subsystem(dev));
0193ad26ba121f3df259cc8b3bab54a99b8e5252Cristian RodrÃguez event->ifindex = udev_device_get_ifindex(dev);
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering if (streq(udev_device_get_subsystem(dev), "firmware"))
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering udev_queue_export_device_queued(udev_queue_export, dev);
if (major(event->devnum) != 0 && event->devnum == loop_event->devnum && event->is_block == loop_event->is_block)
if (major(event->devnum) != 0 && (event->devnum != loop_event->devnum || event->is_block != loop_event->is_block))
#ifdef HAVE_FIRMWARE
const char *str;
goto out;
goto out;
stop_exec_queue = true;
stop_exec_queue = false;
reload = true;
char *key;
char *val;
children_max = i;
udev_exit = true;
out:
char *buf;
int fd;
if (fd >= 0) {
switch (signo) {
case SIGINT:
case SIGTERM:
udev_exit = true;
case SIGCHLD:
int status;
if (pid <= 0)
case SIGHUP:
reload = true;
FILE *f;
strscpyl(modules, sizeof(modules), ROOTPREFIX "/lib/modules/", kernel.release, "/modules.devname", NULL);
if (f == NULL)
const char *modname;
const char *devname;
const char *devno;
char type;
if (s == NULL)
if (s == NULL)
if (s == NULL)
if (s != NULL)
fclose(f);
int fd, n;
n = sd_listen_fds(true);
if (ctrl >= 0)
if (netlink >= 0)
* udev.children-max=<number of workers> events are fully serialized if set to 1
size_t l;
char *s, *opt;
s = strndup(w, l);
opt = s;
int prio;
free(s);
int daemonize = false;
goto exit;
log_open();
int option;
switch (option) {
daemonize = true;
debug = true;
resolve_names = 0;
goto exit;
goto exit;
goto exit;
goto exit;
if (getuid() != 0) {
goto exit;
if (daemonize) {
int fd;
if (fd >= 0) {
goto exit;
goto exit;
goto exit;
goto exit;
goto exit;
goto exit;
goto exit;
if (daemonize) {
switch (pid) {
goto exit;
goto exit_daemonize;
setsid();
if (!debug) {
int fd;
if (fd >= 0) {
if (fd_inotify < 0) {
goto exit;
if (fd_signal < 0) {
goto exit;
goto exit;
goto exit;
if (fd_ep < 0) {
goto exit;
goto exit;
if (children_max <= 0) {
int fdcount;
int timeout;
if (udev_exit) {
if (fd_ctrl >= 0) {
if (fd_inotify >= 0) {
if (udev_cgroup)
if (fdcount < 0)
if (fdcount == 0) {
if (udev_exit) {
for (i = 0; i < fdcount; i++) {
is_worker = true;
is_netlink = true;
is_signal = true;
is_inotify = true;
is_ctrl = true;
reload = true;
reload = true;
if (reload) {
reload = false;
if (is_worker)
if (is_netlink) {
if (is_signal) {
if (udev_exit)
if (is_inotify)
if (is_ctrl)
exit:
if (fd_ep >= 0)
if (fd_signal >= 0)
label_finish();
log_close();
return rc;