Merge branch 'pm-sleep' into pm-for-linus
[deliverable/linux.git] / kernel / kmod.c
index 2142687094d355c1321438f51fdc9cd0fe6e367b..a0a88543934ec44a2218c8a654f378501d754336 100644 (file)
@@ -34,6 +34,9 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/resource.h>
+#include <linux/notifier.h>
+#include <linux/suspend.h>
+#include <linux/rwsem.h>
 #include <asm/uaccess.h>
 
 #include <trace/events/module.h>
@@ -48,6 +51,7 @@ static struct workqueue_struct *khelper_wq;
 static kernel_cap_t usermodehelper_bset = CAP_FULL_SET;
 static kernel_cap_t usermodehelper_inheritable = CAP_FULL_SET;
 static DEFINE_SPINLOCK(umh_sysctl_lock);
+static DECLARE_RWSEM(umhelper_sem);
 
 #ifdef CONFIG_MODULES
 
@@ -273,6 +277,7 @@ static void __call_usermodehelper(struct work_struct *work)
  * If set, call_usermodehelper_exec() will exit immediately returning -EBUSY
  * (used for preventing user land processes from being created after the user
  * land has been frozen during a system-wide hibernation or suspend operation).
+ * Should always be manipulated under umhelper_sem acquired for write.
  */
 static int usermodehelper_disabled = 1;
 
@@ -291,6 +296,18 @@ static DECLARE_WAIT_QUEUE_HEAD(running_helpers_waitq);
  */
 #define RUNNING_HELPERS_TIMEOUT        (5 * HZ)
 
+void read_lock_usermodehelper(void)
+{
+       down_read(&umhelper_sem);
+}
+EXPORT_SYMBOL_GPL(read_lock_usermodehelper);
+
+void read_unlock_usermodehelper(void)
+{
+       up_read(&umhelper_sem);
+}
+EXPORT_SYMBOL_GPL(read_unlock_usermodehelper);
+
 /**
  * usermodehelper_disable - prevent new helpers from being started
  */
@@ -298,8 +315,10 @@ int usermodehelper_disable(void)
 {
        long retval;
 
+       down_write(&umhelper_sem);
        usermodehelper_disabled = 1;
-       smp_mb();
+       up_write(&umhelper_sem);
+
        /*
         * From now on call_usermodehelper_exec() won't start any new
         * helpers, so it is sufficient if running_helpers turns out to
@@ -312,7 +331,9 @@ int usermodehelper_disable(void)
        if (retval)
                return 0;
 
+       down_write(&umhelper_sem);
        usermodehelper_disabled = 0;
+       up_write(&umhelper_sem);
        return -EAGAIN;
 }
 
@@ -321,7 +342,9 @@ int usermodehelper_disable(void)
  */
 void usermodehelper_enable(void)
 {
+       down_write(&umhelper_sem);
        usermodehelper_disabled = 0;
+       up_write(&umhelper_sem);
 }
 
 /**
This page took 0.036931 seconds and 5 git commands to generate.