Merge tag 'modules-next-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[firefly-linux-kernel-4.4.55.git] / kernel / module.c
index 381105b2aaae30d8a79893a1df0b86d1949db672..3965511ae1333d5bcf0d50ac43bd031be76a823b 100644 (file)
@@ -3074,6 +3074,32 @@ static int may_init_module(void)
        return 0;
 }
 
+/*
+ * Can't use wait_event_interruptible() because our condition
+ * 'finished_loading()' contains a blocking primitive itself (mutex_lock).
+ */
+static int wait_finished_loading(struct module *mod)
+{
+       DEFINE_WAIT_FUNC(wait, woken_wake_function);
+       int ret = 0;
+
+       add_wait_queue(&module_wq, &wait);
+       for (;;) {
+               if (finished_loading(mod->name))
+                       break;
+
+               if (signal_pending(current)) {
+                       ret = -ERESTARTSYS;
+                       break;
+               }
+
+               wait_woken(&wait, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT);
+       }
+       remove_wait_queue(&module_wq, &wait);
+
+       return ret;
+}
+
 /*
  * We try to place it in the list now to make sure it's unique before
  * we dedicate too many resources.  In particular, temporary percpu
@@ -3094,8 +3120,8 @@ again:
                    || old->state == MODULE_STATE_UNFORMED) {
                        /* Wait in case it fails to load. */
                        mutex_unlock(&module_mutex);
-                       err = wait_event_interruptible(module_wq,
-                                              finished_loading(mod->name));
+
+                       err = wait_finished_loading(mod);
                        if (err)
                                goto out_unlocked;
                        goto again;