]> git.neil.brown.name Git - history.git/commitdiff
[PATCH] module load notification
authorJohn Levon <levon@movementarian.org>
Tue, 1 Apr 2003 13:06:51 +0000 (05:06 -0800)
committerLinus Torvalds <torvalds@home.transmeta.com>
Tue, 1 Apr 2003 13:06:51 +0000 (05:06 -0800)
This implements a simple notifier so oprofile can notice removed and
added modules properly

drivers/oprofile/buffer_sync.c
drivers/oprofile/event_buffer.h
include/linux/module.h
kernel/module.c

index 9162f38d83954c9d49c1e9513b83818e8473e3e4..14f2ad612a4c658d0dfbadf27fc010312c3779e2 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/notifier.h>
 #include <linux/dcookies.h>
 #include <linux/profile.h>
+#include <linux/module.h>
 #include <linux/fs.h>
  
 #include "oprofile_stats.h"
@@ -67,6 +68,19 @@ static int mm_notify(struct notifier_block * self, unsigned long val, void * dat
 }
 
  
+static int module_load_notify(struct notifier_block * self, unsigned long val, void * data)
+{
+       if (val != MODULE_STATE_COMING)
+               return 0;
+
+       sync_cpu_buffers();
+       down(&buffer_sem);
+       add_event_entry(ESCAPE_CODE);
+       add_event_entry(MODULE_LOADED_CODE);
+       up(&buffer_sem);
+       return 0;
+}
+
 static struct notifier_block exit_task_nb = {
        .notifier_call  = exit_task_notify,
 };
@@ -79,6 +93,10 @@ static struct notifier_block exit_mmap_nb = {
        .notifier_call  = mm_notify,
 };
  
+static struct notifier_block module_load_nb = {
+       .notifier_call = module_load_notify,
+};
+
  
 int sync_start(void)
 {
@@ -98,9 +116,14 @@ int sync_start(void)
        err = profile_event_register(EXEC_UNMAP, &exec_unmap_nb);
        if (err)
                goto out3;
+       err = register_module_notifier(&module_load_nb);
+       if (err)
+               goto out4;
 
 out:
        return err;
+out4:
+       profile_event_unregister(EXEC_UNMAP, &exec_unmap_nb);
 out3:
        profile_event_unregister(EXIT_MMAP, &exit_mmap_nb);
 out2:
@@ -113,6 +136,7 @@ out1:
 
 void sync_stop(void)
 {
+       unregister_module_notifier(&module_load_nb);
        profile_event_unregister(EXIT_TASK, &exit_task_nb);
        profile_event_unregister(EXIT_MMAP, &exit_mmap_nb);
        profile_event_unregister(EXEC_UNMAP, &exec_unmap_nb);
index f0dea9bf8d1afa9634ba449a8941ee550a2f4af1..74382d3b75033d197d732811598cb39cbeeddad5 100644 (file)
@@ -24,12 +24,13 @@ void wake_up_buffer_waiter(void);
  * then one of the following codes, then the
  * relevant data.
  */
-#define ESCAPE_CODE            ~0UL
+#define ESCAPE_CODE                    ~0UL
 #define CTX_SWITCH_CODE                1
 #define CPU_SWITCH_CODE                2
 #define COOKIE_SWITCH_CODE             3
 #define KERNEL_ENTER_SWITCH_CODE       4
 #define KERNEL_EXIT_SWITCH_CODE                5
+#define MODULE_LOADED_CODE             6
  
 /* add data to the event buffer */
 void add_event_entry(unsigned long data);
index 8aef11352270b519401a687b74520c9b156ecf3e..57918bfaba2567a820c48242a45168fa7f98e26a 100644 (file)
@@ -115,6 +115,8 @@ extern const struct gtype##_id __mod_##gtype##_table                \
 /* Given an address, look for it in the exception tables */
 const struct exception_table_entry *search_exception_tables(unsigned long add);
 
+struct notifier_block;
+
 #ifdef CONFIG_MODULES
 
 /* Get/put a kernel symbol (calls must be symmetric) */
@@ -329,6 +331,9 @@ const char *module_address_lookup(unsigned long addr,
 /* For extable.c to search modules' exception tables. */
 const struct exception_table_entry *search_module_extables(unsigned long addr);
 
+int register_module_notifier(struct notifier_block * nb);
+int unregister_module_notifier(struct notifier_block * nb);
+
 #else /* !CONFIG_MODULES... */
 #define EXPORT_SYMBOL(sym)
 #define EXPORT_SYMBOL_GPL(sym)
@@ -373,6 +378,18 @@ static inline const char *module_address_lookup(unsigned long addr,
 {
        return NULL;
 }
+
+static inline int register_module_notifier(struct notifier_block * nb)
+{
+       /* no events will happen anyway, so this can always succeed */
+       return 0;
+}
+
+static inline int unregister_module_notifier(struct notifier_block * nb)
+{
+       return 0;
+}
+
 #endif /* CONFIG_MODULES */
 
 #ifdef MODULE
index 163e5c00e74c8c1224d756e63856fd274971d6f2..f37abf4c1e1b728bf381ede1175f9970202baf8f 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/errno.h>
 #include <linux/err.h>
 #include <linux/vermagic.h>
+#include <linux/notifier.h>
 #include <asm/uaccess.h>
 #include <asm/semaphore.h>
 #include <asm/pgalloc.h>
@@ -59,6 +60,29 @@ static spinlock_t modlist_lock = SPIN_LOCK_UNLOCKED;
 static DECLARE_MUTEX(module_mutex);
 static LIST_HEAD(modules);
 
+static DECLARE_MUTEX(notify_mutex);
+static struct notifier_block * module_notify_list;
+
+int register_module_notifier(struct notifier_block * nb)
+{
+       int err;
+       down(&notify_mutex);
+       err = notifier_chain_register(&module_notify_list, nb);
+       up(&notify_mutex);
+       return err;
+}
+EXPORT_SYMBOL(register_module_notifier);
+
+int unregister_module_notifier(struct notifier_block * nb)
+{
+       int err;
+       down(&notify_mutex);
+       err = notifier_chain_unregister(&module_notify_list, nb);
+       up(&notify_mutex);
+       return err;
+}
+EXPORT_SYMBOL(unregister_module_notifier);
+
 /* We require a truly strong try_module_get() */
 static inline int strong_try_module_get(struct module *mod)
 {
@@ -1373,6 +1397,10 @@ sys_init_module(void *umod,
        /* Drop lock so they can recurse */
        up(&module_mutex);
 
+       down(&notify_mutex);
+       notifier_call_chain(&module_notify_list, MODULE_STATE_COMING, mod);
+       up(&notify_mutex);
+
        /* Start the module */
        ret = mod->init();
        if (ret < 0) {