]> git.proxmox.com Git - mirror_spl.git/commitdiff
Fix spl_kmem_init_kallsyms_lookup() panic
authorBrian Behlendorf <behlendorf1@llnl.gov>
Wed, 19 Dec 2012 01:02:27 +0000 (17:02 -0800)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Wed, 19 Dec 2012 17:06:35 +0000 (09:06 -0800)
Due to I/O buffering the helper may return successfully before
the proc handler has a chance to execute.  To catch this case
wait up to 1 second to verify spl_kallsyms_lookup_name_fn was
updated to a non SYMBOL_POISON value.

Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes zfsonlinux/zfs#699
Closes zfsonlinux/zfs#859

include/linux/kallsyms_compat.h
module/spl/spl-generic.c
module/spl/spl-proc.c

index 34c45ea3a35f067f9bad6181e627f4f9c3732b10..fbe33e8e6a00412544440ab9e5a3093da876ca70 100644 (file)
@@ -34,6 +34,7 @@
 
 #else
 
+extern wait_queue_head_t spl_kallsyms_lookup_name_waitq;
 typedef unsigned long (*kallsyms_lookup_name_t)(const char *);
 extern kallsyms_lookup_name_t spl_kallsyms_lookup_name_fn;
 #define spl_kallsyms_lookup_name(name) spl_kallsyms_lookup_name_fn(name)
index cc2766452d797afb37e5c05545440012f5b8985e..22ea5078116187893bb2847496cb7318d19c51c9 100644 (file)
@@ -64,6 +64,7 @@ proc_t p0 = { 0 };
 EXPORT_SYMBOL(p0);
 
 #ifndef HAVE_KALLSYMS_LOOKUP_NAME
+DECLARE_WAIT_QUEUE_HEAD(spl_kallsyms_lookup_name_waitq);
 kallsyms_lookup_name_t spl_kallsyms_lookup_name_fn = SYMBOL_POISON;
 #endif
 
@@ -607,6 +608,24 @@ set_kallsyms_lookup_name(void)
        int rc;
 
        rc = call_usermodehelper(argv[0], argv, envp, 1);
+
+       /*
+        * Due to I/O buffering the helper may return successfully before
+        * the proc handler has a chance to execute.  To catch this case
+        * wait up to 1 second to verify spl_kallsyms_lookup_name_fn was
+        * updated to a non SYMBOL_POISON value.
+        */
+       if (rc == 0) {
+               rc = wait_event_timeout(spl_kallsyms_lookup_name_waitq,
+                   spl_kallsyms_lookup_name_fn != SYMBOL_POISON, HZ);
+               if (rc == 0)
+                       rc = -ETIMEDOUT;
+               else if (spl_kallsyms_lookup_name_fn == SYMBOL_POISON)
+                       rc = -EFAULT;
+               else
+                       rc = 0;
+       }
+
        if (rc)
                printk("SPL: Failed user helper '%s %s %s', rc = %d\n",
                       argv[0], argv[1], argv[2], rc);
index 152abff7f54bee30f20dfafd410f171a202d6cdf..2fb295439bab7801bd3114865b8a2549a7e0c50c 100644 (file)
@@ -546,6 +546,8 @@ SPL_PROC_HANDLER(proc_dokallsyms_lookup_name)
 
                 spl_kallsyms_lookup_name_fn =
                        (kallsyms_lookup_name_t)simple_strtoul(str, &end, 16);
+               wake_up(&spl_kallsyms_lookup_name_waitq);
+
                if (str == end)
                        SRETURN(-EINVAL);