From: Alan Stern Notifier chain re-implementation (as635b): Update the usages of the various die_chains. This includes changes posted by Keith Owens, including the addition of an unregister routine (which is now safe). Signed-off-by: Alan Stern Signed-off-by: Chandra Seetharaman Acked-By: Keith Owens Signed-off-by: Andrew Morton --- arch/i386/kernel/traps.c | 17 ++++++++--------- arch/ia64/kernel/traps.c | 6 +++--- arch/powerpc/kernel/traps.c | 16 ++++++++-------- arch/sparc64/kernel/traps.c | 17 +++++++++-------- arch/x86_64/kernel/traps.c | 18 +++++++++--------- include/asm-i386/kdebug.h | 10 ++++------ include/asm-ia64/kdebug.h | 4 ++-- include/asm-powerpc/kdebug.h | 12 ++++-------- include/asm-sparc64/kdebug.h | 11 ++++------- include/asm-x86_64/kdebug.h | 23 +++++++++++------------ 10 files changed, 62 insertions(+), 72 deletions(-) diff -puN arch/i386/kernel/traps.c~notifier-chain-update-die_chain-changes arch/i386/kernel/traps.c --- devel/arch/i386/kernel/traps.c~notifier-chain-update-die_chain-changes 2006-02-22 17:42:11.000000000 -0800 +++ devel-akpm/arch/i386/kernel/traps.c 2006-02-22 17:43:13.000000000 -0800 @@ -92,22 +92,21 @@ asmlinkage void spurious_interrupt_bug(v asmlinkage void machine_check(void); static int kstack_depth_to_print = 24; -struct notifier_block *i386die_chain; -static DEFINE_SPINLOCK(die_notifier_lock); +ATOMIC_NOTIFIER_HEAD(i386die_chain); int register_die_notifier(struct notifier_block *nb) { - int err = 0; - unsigned long flags; - vmalloc_sync_all(); - spin_lock_irqsave(&die_notifier_lock, flags); - err = notifier_chain_register(&i386die_chain, nb); - spin_unlock_irqrestore(&die_notifier_lock, flags); - return err; + return atomic_notifier_chain_register(&i386die_chain, nb); } EXPORT_SYMBOL(register_die_notifier); +int unregister_die_notifier(struct notifier_block *nb) +{ + return atomic_notifier_chain_unregister(&i386die_chain, nb); +} +EXPORT_SYMBOL(unregister_die_notifier); + static inline int valid_stack_ptr(struct thread_info *tinfo, void *p) { return p > (void *)tinfo && diff -puN arch/ia64/kernel/traps.c~notifier-chain-update-die_chain-changes arch/ia64/kernel/traps.c --- devel/arch/ia64/kernel/traps.c~notifier-chain-update-die_chain-changes 2006-02-22 17:42:11.000000000 -0800 +++ devel-akpm/arch/ia64/kernel/traps.c 2006-02-22 17:42:11.000000000 -0800 @@ -30,19 +30,19 @@ extern spinlock_t timerlist_lock; fpswa_interface_t *fpswa_interface; EXPORT_SYMBOL(fpswa_interface); -struct notifier_block *ia64die_chain; +ATOMIC_NOTIFIER_HEAD(ia64die_chain); int register_die_notifier(struct notifier_block *nb) { - return notifier_chain_register(&ia64die_chain, nb); + return atomic_notifier_chain_register(&ia64die_chain, nb); } EXPORT_SYMBOL_GPL(register_die_notifier); int unregister_die_notifier(struct notifier_block *nb) { - return notifier_chain_unregister(&ia64die_chain, nb); + return atomic_notifier_chain_unregister(&ia64die_chain, nb); } EXPORT_SYMBOL_GPL(unregister_die_notifier); diff -puN arch/powerpc/kernel/traps.c~notifier-chain-update-die_chain-changes arch/powerpc/kernel/traps.c --- devel/arch/powerpc/kernel/traps.c~notifier-chain-update-die_chain-changes 2006-02-22 17:42:11.000000000 -0800 +++ devel-akpm/arch/powerpc/kernel/traps.c 2006-02-22 17:42:11.000000000 -0800 @@ -74,19 +74,19 @@ EXPORT_SYMBOL(__debugger_dabr_match); EXPORT_SYMBOL(__debugger_fault_handler); #endif -struct notifier_block *powerpc_die_chain; -static DEFINE_SPINLOCK(die_notifier_lock); +ATOMIC_NOTIFIER_HEAD(powerpc_die_chain); int register_die_notifier(struct notifier_block *nb) { - int err = 0; - unsigned long flags; + return atomic_notifier_chain_register(&powerpc_die_chain, nb); +} +EXPORT_SYMBOL(register_die_notifier); - spin_lock_irqsave(&die_notifier_lock, flags); - err = notifier_chain_register(&powerpc_die_chain, nb); - spin_unlock_irqrestore(&die_notifier_lock, flags); - return err; +int unregister_die_notifier(struct notifier_block *nb) +{ + return atomic_notifier_chain_unregister(&powerpc_die_chain, nb); } +EXPORT_SYMBOL(unregister_die_notifier); /* * Trap & Exception support diff -puN arch/sparc64/kernel/traps.c~notifier-chain-update-die_chain-changes arch/sparc64/kernel/traps.c --- devel/arch/sparc64/kernel/traps.c~notifier-chain-update-die_chain-changes 2006-02-22 17:42:11.000000000 -0800 +++ devel-akpm/arch/sparc64/kernel/traps.c 2006-02-22 17:42:11.000000000 -0800 @@ -43,18 +43,19 @@ #include #endif -struct notifier_block *sparc64die_chain; -static DEFINE_SPINLOCK(die_notifier_lock); +ATOMIC_NOTIFIER_HEAD(sparc64die_chain); int register_die_notifier(struct notifier_block *nb) { - int err = 0; - unsigned long flags; - spin_lock_irqsave(&die_notifier_lock, flags); - err = notifier_chain_register(&sparc64die_chain, nb); - spin_unlock_irqrestore(&die_notifier_lock, flags); - return err; + return atomic_notifier_chain_register(&sparc64die_chain, nb); } +EXPORT_SYMBOL(register_die_notifier); + +int unregister_die_notifier(struct notifier_block *nb) +{ + return atomic_notifier_chain_unregister(&sparc64die_chain, nb); +} +EXPORT_SYMBOL(unregister_die_notifier); /* When an irrecoverable trap occurs at tl > 0, the trap entry * code logs the trap state registers at every level in the trap diff -puN arch/x86_64/kernel/traps.c~notifier-chain-update-die_chain-changes arch/x86_64/kernel/traps.c --- devel/arch/x86_64/kernel/traps.c~notifier-chain-update-die_chain-changes 2006-02-22 17:42:11.000000000 -0800 +++ devel-akpm/arch/x86_64/kernel/traps.c 2006-02-22 17:42:11.000000000 -0800 @@ -69,20 +69,20 @@ asmlinkage void alignment_check(void); asmlinkage void machine_check(void); asmlinkage void spurious_interrupt_bug(void); -struct notifier_block *die_chain; -static DEFINE_SPINLOCK(die_notifier_lock); +ATOMIC_NOTIFIER_HEAD(die_chain); int register_die_notifier(struct notifier_block *nb) { - int err = 0; - unsigned long flags; - vmalloc_sync_all(); - spin_lock_irqsave(&die_notifier_lock, flags); - err = notifier_chain_register(&die_chain, nb); - spin_unlock_irqrestore(&die_notifier_lock, flags); - return err; + return atomic_notifier_chain_register(&die_chain, nb); +} +EXPORT_SYMBOL(register_die_notifier); + +int unregister_die_notifier(struct notifier_block *nb) +{ + return atomic_notifier_chain_unregister(&die_chain, nb); } +EXPORT_SYMBOL(unregister_die_notifier); static inline void conditional_sti(struct pt_regs *regs) { diff -puN include/asm-i386/kdebug.h~notifier-chain-update-die_chain-changes include/asm-i386/kdebug.h --- devel/include/asm-i386/kdebug.h~notifier-chain-update-die_chain-changes 2006-02-22 17:42:11.000000000 -0800 +++ devel-akpm/include/asm-i386/kdebug.h 2006-02-22 17:42:11.000000000 -0800 @@ -17,11 +17,9 @@ struct die_args { int signr; }; -/* Note - you should never unregister because that can race with NMIs. - If you really want to do it first unregister - then synchronize_sched - then free. - */ -int register_die_notifier(struct notifier_block *nb); -extern struct notifier_block *i386die_chain; +extern int register_die_notifier(struct notifier_block *); +extern int unregister_die_notifier(struct notifier_block *); +extern struct atomic_notifier_head i386die_chain; /* Grossly misnamed. */ @@ -51,7 +49,7 @@ static inline int notify_die(enum die_va .trapnr = trap, .signr = sig }; - return notifier_call_chain(&i386die_chain, val, &args); + return atomic_notifier_call_chain(&i386die_chain, val, &args); } #endif diff -puN include/asm-ia64/kdebug.h~notifier-chain-update-die_chain-changes include/asm-ia64/kdebug.h --- devel/include/asm-ia64/kdebug.h~notifier-chain-update-die_chain-changes 2006-02-22 17:42:11.000000000 -0800 +++ devel-akpm/include/asm-ia64/kdebug.h 2006-02-22 17:42:11.000000000 -0800 @@ -40,7 +40,7 @@ struct die_args { extern int register_die_notifier(struct notifier_block *); extern int unregister_die_notifier(struct notifier_block *); -extern struct notifier_block *ia64die_chain; +extern struct atomic_notifier_head ia64die_chain; enum die_val { DIE_BREAK = 1, @@ -81,7 +81,7 @@ static inline int notify_die(enum die_va .signr = sig }; - return notifier_call_chain(&ia64die_chain, val, &args); + return atomic_notifier_call_chain(&ia64die_chain, val, &args); } #endif diff -puN include/asm-powerpc/kdebug.h~notifier-chain-update-die_chain-changes include/asm-powerpc/kdebug.h --- devel/include/asm-powerpc/kdebug.h~notifier-chain-update-die_chain-changes 2006-02-22 17:42:11.000000000 -0800 +++ devel-akpm/include/asm-powerpc/kdebug.h 2006-02-22 17:42:11.000000000 -0800 @@ -16,13 +16,9 @@ struct die_args { int signr; }; -/* - Note - you should never unregister because that can race with NMIs. - If you really want to do it first unregister - then synchronize_sched - - then free. - */ -int register_die_notifier(struct notifier_block *nb); -extern struct notifier_block *powerpc_die_chain; +extern int register_die_notifier(struct notifier_block *); +extern int unregister_die_notifier(struct notifier_block *); +extern struct atomic_notifier_head powerpc_die_chain; /* Grossly misnamed. */ enum die_val { @@ -37,7 +33,7 @@ enum die_val { static inline int notify_die(enum die_val val,char *str,struct pt_regs *regs,long err,int trap, int sig) { struct die_args args = { .regs=regs, .str=str, .err=err, .trapnr=trap,.signr=sig }; - return notifier_call_chain(&powerpc_die_chain, val, &args); + return atomic_notifier_call_chain(&powerpc_die_chain, val, &args); } #endif /* __KERNEL__ */ diff -puN include/asm-sparc64/kdebug.h~notifier-chain-update-die_chain-changes include/asm-sparc64/kdebug.h --- devel/include/asm-sparc64/kdebug.h~notifier-chain-update-die_chain-changes 2006-02-22 17:42:11.000000000 -0800 +++ devel-akpm/include/asm-sparc64/kdebug.h 2006-02-22 17:42:11.000000000 -0800 @@ -15,12 +15,9 @@ struct die_args { int signr; }; -/* Note - you should never unregister because that can race with NMIs. - * If you really want to do it first unregister - then synchronize_sched - * - then free. - */ -int register_die_notifier(struct notifier_block *nb); -extern struct notifier_block *sparc64die_chain; +extern int register_die_notifier(struct notifier_block *); +extern int unregister_die_notifier(struct notifier_block *); +extern struct atomic_notifier_head sparc64die_chain; extern void bad_trap(struct pt_regs *, long); @@ -46,7 +43,7 @@ static inline int notify_die(enum die_va .trapnr = trap, .signr = sig }; - return notifier_call_chain(&sparc64die_chain, val, &args); + return atomic_notifier_call_chain(&sparc64die_chain, val, &args); } #endif diff -puN include/asm-x86_64/kdebug.h~notifier-chain-update-die_chain-changes include/asm-x86_64/kdebug.h --- devel/include/asm-x86_64/kdebug.h~notifier-chain-update-die_chain-changes 2006-02-22 17:42:11.000000000 -0800 +++ devel-akpm/include/asm-x86_64/kdebug.h 2006-02-22 17:42:11.000000000 -0800 @@ -5,21 +5,20 @@ struct pt_regs; -struct die_args { +struct die_args { struct pt_regs *regs; const char *str; - long err; + long err; int trapnr; int signr; -}; +}; + +extern int register_die_notifier(struct notifier_block *); +extern int unregister_die_notifier(struct notifier_block *); +extern struct atomic_notifier_head die_chain; -/* Note - you should never unregister because that can race with NMIs. - If you really want to do it first unregister - then synchronize_sched - then free. - */ -int register_die_notifier(struct notifier_block *nb); -extern struct notifier_block *die_chain; /* Grossly misnamed. */ -enum die_val { +enum die_val { DIE_OOPS = 1, DIE_INT3, DIE_DEBUG, @@ -33,8 +32,8 @@ enum die_val { DIE_CALL, DIE_NMI_IPI, DIE_PAGE_FAULT, -}; - +}; + static inline int notify_die(enum die_val val, const char *str, struct pt_regs *regs, long err, int trap, int sig) { @@ -45,7 +44,7 @@ static inline int notify_die(enum die_va .trapnr = trap, .signr = sig }; - return notifier_call_chain(&die_chain, val, &args); + return atomic_notifier_call_chain(&die_chain, val, &args); } extern int printk_address(unsigned long address); _