---
 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[]);
 
