X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fudev%2Fudevd.c;h=b69f3f87de90a12625bfeb7674651d5f78b5e46b;hp=2ac9fde04914508e9617eb41f8a79d9fc2fd2e98;hb=40fe8b11be9c1a1b38b91db097a5d6ebfa99304c;hpb=145dae7eb3367933e0d0bfcde3a7a77bb549aa61 diff --git a/src/udev/udevd.c b/src/udev/udevd.c index 2ac9fde04..b69f3f87d 100644 --- a/src/udev/udevd.c +++ b/src/udev/udevd.c @@ -95,8 +95,9 @@ struct event { size_t devpath_len; const char *devpath_old; dev_t devnum; - bool is_block; int ifindex; + bool is_block; + bool nodelay; }; static inline struct event *node_to_event(struct udev_list_node *node) @@ -121,7 +122,7 @@ struct worker { struct udev_monitor *monitor; enum worker_state state; struct event *event; - unsigned long long event_start_usec; + usec_t event_start_usec; }; /* passed from worker to main process */ @@ -377,7 +378,7 @@ out: worker->monitor = worker_monitor; worker->pid = pid; worker->state = WORKER_RUNNING; - worker->event_start_usec = now_usec(); + worker->event_start_usec = now(CLOCK_MONOTONIC); worker->event = event; event->state = EVENT_RUNNING; udev_list_node_append(&worker->node, &worker_list); @@ -408,7 +409,7 @@ static void event_run(struct event *event) worker_ref(worker); worker->event = event; worker->state = WORKER_RUNNING; - worker->event_start_usec = now_usec(); + worker->event_start_usec = now(CLOCK_MONOTONIC); event->state = EVENT_RUNNING; return; } @@ -438,8 +439,10 @@ static int event_queue_insert(struct udev_device *dev) event->devpath_len = strlen(event->devpath); event->devpath_old = udev_device_get_devpath_old(dev); event->devnum = udev_device_get_devnum(dev); - event->is_block = (strcmp("block", udev_device_get_subsystem(dev)) == 0); + event->is_block = streq("block", udev_device_get_subsystem(dev)); event->ifindex = udev_device_get_ifindex(dev); + if (streq(udev_device_get_subsystem(dev), "firmware")) + event->nodelay = true; udev_queue_export_device_queued(udev_queue_export, dev); log_debug("seq %llu queued, '%s' '%s'\n", udev_device_get_seqnum(dev), @@ -519,6 +522,10 @@ static bool is_devpath_busy(struct event *event) return true; } + /* allow to bypass the dependency tracking */ + if (event->nodelay) + continue; + /* parent device event found */ if (event->devpath[common] == '/') { event->delaying_seqnum = loop_event->seqnum; @@ -806,8 +813,8 @@ static void static_dev_create_from_modules(struct udev *udev) FILE *f; uname(&kernel); - util_strscpyl(modules, sizeof(modules), "/lib/modules/", kernel.release, "/modules.devname", NULL); - f = fopen(modules, "r"); + util_strscpyl(modules, sizeof(modules), ROOTPREFIX "/lib/modules/", kernel.release, "/modules.devname", NULL); + f = fopen(modules, "re"); if (f == NULL) return; @@ -845,10 +852,11 @@ static void static_dev_create_from_modules(struct udev *udev) if (sscanf(devno, "%c%u:%u", &type, &maj, &min) != 3) continue; + mode = 0600; if (type == 'c') - mode = S_IFCHR; + mode |= S_IFCHR; else if (type == 'b') - mode = S_IFBLK; + mode |= S_IFBLK; else continue; @@ -870,7 +878,7 @@ static int mem_size_mb(void) char buf[4096]; long int memsize = -1; - f = fopen("/proc/meminfo", "r"); + f = fopen("/proc/meminfo", "re"); if (f == NULL) return -1; @@ -890,7 +898,6 @@ static int mem_size_mb(void) static int convert_db(struct udev *udev) { char filename[UTIL_PATH_SIZE]; - FILE *f; struct udev_enumerate *udev_enumerate; struct udev_list_entry *list_entry; @@ -899,19 +906,14 @@ static int convert_db(struct udev *udev) return 0; /* make sure we do not get here again */ - mkdir_parents("/run/udev/data", 0755); - mkdir(filename, 0755); + mkdir_p("/run/udev/data", 0755); /* old database */ util_strscpyl(filename, sizeof(filename), "/dev/.udev/db", NULL); if (access(filename, F_OK) < 0) return 0; - f = fopen("/dev/kmsg", "w"); - if (f != NULL) { - fprintf(f, "<30>udevd[%u]: converting old udev database\n", getpid()); - fclose(f); - } + print_kmsg("converting old udev database\n"); udev_enumerate = udev_enumerate_new(udev); if (udev_enumerate == NULL) @@ -1013,10 +1015,54 @@ static int systemd_fds(struct udev *udev, int *rctrl, int *rnetlink) return 0; } +/* + * read the kernel commandline, in case we need to get into debug mode + * udev.log-priority= syslog priority + * udev.children-max= events are fully serialized if set to 1 + * udev.exec-delay= delay execution of every executed program + */ +static void kernel_cmdline_options(struct udev *udev) +{ + char *line, *w, *state; + size_t l; + + if (read_one_line_file("/proc/cmdline", &line) < 0) + return; + + FOREACH_WORD_QUOTED(w, l, line, state) { + char *s, *opt; + + s = strndup(w, l); + if (!s) + break; + + /* accept the same options for the initrd, prefixed with "rd." */ + if (in_initrd() && startswith(s, "rd.")) + opt = s + 3; + else + opt = s; + + if (startswith(opt, "udev.log-priority=")) { + int prio; + + prio = util_log_priority(opt + 18); + log_set_max_level(prio); + udev_set_log_priority(udev, prio); + } else if (startswith(opt, "udev.children-max=")) { + children_max = strtoul(opt + 18, NULL, 0); + } else if (startswith(opt, "udev.exec-delay=")) { + exec_delay = strtoul(opt + 16, NULL, 0); + } + + free(s); + } + + free(line); +} + int main(int argc, char *argv[]) { struct udev *udev; - FILE *f; sigset_t mask; int daemonize = false; int resolve_names = 1; @@ -1041,8 +1087,9 @@ int main(int argc, char *argv[]) if (udev == NULL) goto exit; - log_open(); + log_set_target(LOG_TARGET_AUTO); log_parse_environment(); + log_open(); udev_set_log_fn(udev, udev_main_log); log_debug("version %s\n", VERSION); label_init("/dev"); @@ -1067,7 +1114,7 @@ int main(int argc, char *argv[]) case 'D': debug = true; log_set_max_level(LOG_DEBUG); - udev_set_log_priority(udev, LOG_INFO); + udev_set_log_priority(udev, LOG_DEBUG); break; case 'N': if (strcmp (optarg, "early") == 0) { @@ -1101,39 +1148,7 @@ int main(int argc, char *argv[]) } } - /* - * read the kernel commandline, in case we need to get into debug mode - * udev.log-priority= syslog priority - * udev.children-max= events are fully serialized if set to 1 - * - */ - f = fopen("/proc/cmdline", "r"); - if (f != NULL) { - char cmdline[4096]; - - if (fgets(cmdline, sizeof(cmdline), f) != NULL) { - char *pos; - - pos = strstr(cmdline, "udev.log-priority="); - if (pos != NULL) { - pos += strlen("udev.log-priority="); - udev_set_log_priority(udev, util_log_priority(pos)); - } - - pos = strstr(cmdline, "udev.children-max="); - if (pos != NULL) { - pos += strlen("udev.children-max="); - children_max = strtoul(pos, NULL, 0); - } - - pos = strstr(cmdline, "udev.exec-delay="); - if (pos != NULL) { - pos += strlen("udev.exec-delay="); - exec_delay = strtoul(pos, NULL, 0); - } - } - fclose(f); - } + kernel_cmdline_options(udev); if (getuid() != 0) { fprintf(stderr, "root privileges required\n"); @@ -1147,7 +1162,7 @@ int main(int argc, char *argv[]) mkdir("/run/udev", 0755); - dev_setup(); + dev_setup(NULL); static_dev_create_from_modules(udev); /* before opening new files, make sure std{in,out,err} fds are in a sane state */ @@ -1169,7 +1184,7 @@ int main(int argc, char *argv[]) } if (systemd_fds(udev, &fd_ctrl, &fd_netlink) >= 0) { - /* get control and netlink socket from from systemd */ + /* get control and netlink socket from systemd */ udev_ctrl = udev_ctrl_new_from_fd(udev, fd_ctrl); if (udev_ctrl == NULL) { log_error("error taking over udev control socket"); @@ -1254,11 +1269,7 @@ int main(int argc, char *argv[]) sd_notify(1, "READY=1"); } - f = fopen("/dev/kmsg", "w"); - if (f != NULL) { - fprintf(f, "<30>udevd[%u]: starting version " VERSION "\n", getpid()); - fclose(f); - } + print_kmsg("starting version " VERSION "\n"); if (!debug) { int fd; @@ -1363,7 +1374,7 @@ int main(int argc, char *argv[]) udev_list_node_init(&worker_list); for (;;) { - static unsigned long long last_usec; + static usec_t last_usec; struct epoll_event ev[8]; int fdcount; int timeout; @@ -1434,7 +1445,7 @@ int main(int argc, char *argv[]) if (worker->state != WORKER_RUNNING) continue; - if ((now_usec() - worker->event_start_usec) > 30 * 1000 * 1000) { + if ((now(CLOCK_MONOTONIC) - worker->event_start_usec) > 30 * 1000 * 1000) { log_error("worker [%u] %s timeout; kill it\n", worker->pid, worker->event ? worker->event->devpath : ""); kill(worker->pid, SIGKILL); @@ -1468,13 +1479,13 @@ int main(int argc, char *argv[]) } /* check for changed config, every 3 seconds at most */ - if ((now_usec() - last_usec) > 3 * 1000 * 1000) { + if ((now(CLOCK_MONOTONIC) - last_usec) > 3 * 1000 * 1000) { if (udev_rules_check_timestamp(rules)) reload = true; if (udev_builtin_validate(udev)) reload = true; - last_usec = now_usec(); + last_usec = now(CLOCK_MONOTONIC); } /* reload requested, HUP signal received, rules changed, builtin changed */ @@ -1482,7 +1493,7 @@ int main(int argc, char *argv[]) worker_kill(udev); rules = udev_rules_unref(rules); udev_builtin_exit(udev); - reload = 0; + reload = false; } /* event has finished */ @@ -1494,7 +1505,7 @@ int main(int argc, char *argv[]) dev = udev_monitor_receive_device(monitor); if (dev != NULL) { - udev_device_set_usec_initialized(dev, now_usec()); + udev_device_set_usec_initialized(dev, now(CLOCK_MONOTONIC)); if (event_queue_insert(dev) < 0) udev_device_unref(dev); } @@ -1502,6 +1513,7 @@ int main(int argc, char *argv[]) /* start new events */ if (!udev_list_node_is_empty(&event_list) && !udev_exit && !stop_exec_queue) { + udev_builtin_init(udev); if (rules == NULL) rules = udev_rules_new(udev, resolve_names); if (rules != NULL)