--- src/udev/udev-event.c | 42 ++++++++++++++++++++++++++++++++++++++++++ src/udev/udev.h | 1 + src/udev/udevd.c | 23 +++++++++++++++++++++-- 3 files changed, 64 insertions(+), 2 deletions(-) --- src/udev/udev-event.c +++ src/udev/udev-event.c 2014-09-24 14:32:53.115639820 +0000 @@ -959,6 +959,46 @@ void udev_event_execute_rules(struct ude } } +#ifdef HAVE_KMOD +static inline void udev_check_and_set_kmod(enum udev_builtin_cmd builtin_cmd, struct udev_event *event) { + char filename[UTIL_PATH_SIZE]; + switch (builtin_cmd) { + case UDEV_BUILTIN_KMOD: + snprintf(filename, sizeof(filename), "/run/udev/kmod/%u", (unsigned)getpid()); + touch(filename); + default: + break; + } +} + +static inline void udev_check_and_unset_kmod(enum udev_builtin_cmd builtin_cmd, struct udev_event *event) { + char filename[UTIL_PATH_SIZE]; + switch (builtin_cmd) { + case UDEV_BUILTIN_KMOD: + snprintf(filename, sizeof(filename), "/run/udev/kmod/%u", (unsigned)getpid()); + unlink(filename); + default: + break; + } +} + +bool udev_check_for_kmod(pid_t pid) { + char filename[UTIL_PATH_SIZE]; + struct stat st; + snprintf(filename, sizeof(filename), "/run/udev/kmod/%u", (unsigned)pid); + if (stat(filename, &st) == 0) { + return true; + } + return false; +} +#else +# define udev_set_kmod (a,b) +# define udev_unset_kmod(a,b) +bool udev_check_for_kmod(pid_t pid) { + return false; +} +#endif + void udev_event_execute_run(struct udev_event *event, usec_t timeout_usec, usec_t timeout_warn_usec, const sigset_t *sigmask) { struct udev_list_entry *list_entry; @@ -970,7 +1010,9 @@ void udev_event_execute_run(struct udev_ char command[UTIL_PATH_SIZE]; udev_event_apply_format(event, cmd, command, sizeof(command)); + udev_check_and_set_kmod(builtin_cmd, event); udev_builtin_run(event->dev, builtin_cmd, command, false); + udev_check_and_unset_kmod(builtin_cmd, event); } else { char program[UTIL_PATH_SIZE]; char **envp; --- src/udev/udevd.c +++ src/udev/udevd.c 2014-09-24 15:02:30.895592379 +0000 @@ -76,6 +76,7 @@ static int children_max; static int exec_delay; static usec_t event_timeout_usec = 180 * USEC_PER_SEC; static usec_t event_timeout_warn_usec = 180 * USEC_PER_SEC / 3; +static bool event_killkmod = false; static sigset_t sigmask_orig; static UDEV_LIST(event_list); static UDEV_LIST(worker_list); @@ -1017,6 +1018,12 @@ static void kernel_cmdline_options(struc } event_timeout_usec *= USEC_PER_SEC; event_timeout_warn_usec = (event_timeout_usec / 3) ? : 1; + } else if (startswith(opt, "udev.killkmod=")) { + r = parse_boolean(opt + 14); + if (r < 0) + log_warning("Invalid udev.killkmod Ignoring: %s", opt + 14); + else + event_killkmod = r; } free(s); @@ -1065,7 +1072,7 @@ int main(int argc, char *argv[]) { } for (;;) { - int option, r; + int option; option = getopt_long(argc, argv, "c:de:DtN:hV", options, NULL); if (option == -1) @@ -1356,6 +1363,12 @@ int main(int argc, char *argv[]) { udev_list_node_init(&event_list); udev_list_node_init(&worker_list); + r = mkdir_p("/run/udev/kmod", 0755); + if (r < 0 && errno != EEXIST) { + log_error("could not create /run/udev/kmod: %m"); + goto exit; + } + for (;;) { static usec_t last_usec; struct epoll_event ev[8]; @@ -1440,7 +1453,13 @@ int main(int argc, char *argv[]) { if (worker->state != WORKER_RUNNING) continue; - +#ifdef HAVE_KMOD + if (udev_check_for_kmod(worker->pid)) { + log_debug("worker [%u] %s is using kmod", worker->pid, worker->event->devpath); + if (!event_killkmod) + continue; + } +#endif ts = now(CLOCK_MONOTONIC); if ((ts - worker->event_start_usec) > event_timeout_warn_usec) { --- src/udev/udev.h +++ src/udev/udev.h 2014-09-24 14:33:33.824008084 +0000 @@ -88,6 +88,7 @@ int udev_event_spawn(struct udev_event * char *result, size_t ressize); void udev_event_execute_rules(struct udev_event *event, usec_t timeout_usec, usec_t timeout_warn_usec, struct udev_rules *rules, const sigset_t *sigset); +bool udev_check_for_kmod(pid_t pid); void udev_event_execute_run(struct udev_event *event, usec_t timeout_usec, usec_t timeout_warn_usec, const sigset_t *sigset); int udev_build_argv(struct udev *udev, char *cmd, int *argc, char *argv[]);