Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/percpu
[pandora-kernel.git] / kernel / module.c
index 3a4db71..05ce49c 100644 (file)
 #include <linux/percpu.h>
 #include <linux/kmemleak.h>
 
+#define CREATE_TRACE_POINTS
+#include <trace/events/module.h>
+
+EXPORT_TRACEPOINT_SYMBOL(module_get);
+
 #if 0
 #define DEBUGP printk
 #else
@@ -909,16 +914,18 @@ void __symbol_put(const char *symbol)
 }
 EXPORT_SYMBOL(__symbol_put);
 
+/* Note this assumes addr is a function, which it currently always is. */
 void symbol_put_addr(void *addr)
 {
        struct module *modaddr;
+       unsigned long a = (unsigned long)dereference_function_descriptor(addr);
 
-       if (core_kernel_text((unsigned long)addr))
+       if (core_kernel_text(a))
                return;
 
        /* module_text_address is safe here: we're supposed to have reference
         * to module from symbol_get, so it can't go away. */
-       modaddr = __module_text_address((unsigned long)addr);
+       modaddr = __module_text_address(a);
        BUG_ON(!modaddr);
        module_put(modaddr);
 }
@@ -940,6 +947,8 @@ void module_put(struct module *module)
        if (module) {
                unsigned int cpu = get_cpu();
                local_dec(__module_ref_addr(module, cpu));
+               trace_module_put(module, _RET_IP_,
+                                local_read(__module_ref_addr(module, cpu)));
                /* Maybe they're waiting for us to drop reference? */
                if (unlikely(!module_is_live(module)))
                        wake_up_process(module->waiter);
@@ -1272,6 +1281,10 @@ static void add_notes_attrs(struct module *mod, unsigned int nsect,
        struct module_notes_attrs *notes_attrs;
        struct bin_attribute *nattr;
 
+       /* failed to create section attributes, so can't create notes */
+       if (!mod->sect_attrs)
+               return;
+
        /* Count notes sections and allocate structures.  */
        notes = 0;
        for (i = 0; i < nsect; i++)
@@ -1491,6 +1504,8 @@ static int __unlink_module(void *_mod)
 /* Free a module, remove from lists, etc (must hold module_mutex). */
 static void free_module(struct module *mod)
 {
+       trace_module_free(mod);
+
        /* Delete from various lists */
        stop_machine(__unlink_module, mod, NULL);
        remove_notes_attrs(mod);
@@ -2358,6 +2373,8 @@ static noinline struct module *load_module(void __user *umod,
        /* Get rid of temporary copy */
        vfree(hdr);
 
+       trace_module_load(mod);
+
        /* Done! */
        return mod;