* [PATCH 1/2] add tunable_notifier function ,take2 [not found] <47FF0EA5.8090804@ah.jp.nec.com> @ 2008-04-11 7:53 ` Takenori Nagano 2008-04-11 7:53 ` Takenori Nagano 1 sibling, 0 replies; 14+ messages in thread From: Takenori Nagano @ 2008-04-11 7:53 UTC (permalink / raw) To: linux-kernel, Andrew Morton Cc: nickpiggin, k-miyoshi, greg, Bernhard Walle, kdb, kexec, Randy Dunlap, vgoyal, Eric W. Biederman, Keith Owens [-- Attachment #1: Type: text/plain, Size: 12973 bytes --] This patch adds new notifier function tunable_notifier_chain. Its base is atomic_notifier_chain. Thanks, --- Signed-off-by: Takenori Nagano <t-nagano@ah.jp.nec.com> --- diff -uprN linux-2.6.25-rc8-mm1.orig/include/linux/notifier.h linux-2.6.25-rc8-mm1/include/linux/notifier.h --- linux-2.6.25-rc8-mm1.orig/include/linux/notifier.h 2008-04-08 16:37:43.700000000 +0900 +++ linux-2.6.25-rc8-mm1/include/linux/notifier.h 2008-04-09 20:01:10.328000000 +0900 @@ -13,6 +13,7 @@ #include <linux/mutex.h> #include <linux/rwsem.h> #include <linux/srcu.h> +#include <linux/kobject.h> /* * Notifier chains are of four types: @@ -53,6 +54,13 @@ struct notifier_block { int priority; }; +struct tunable_atomic_notifier_block { + struct notifier_block *nb; + struct tunable_atomic_notifier_head *head; + struct kobject kobj; + char *desc; +}; + struct atomic_notifier_head { spinlock_t lock; struct notifier_block *head; @@ -63,6 +71,13 @@ struct blocking_notifier_head { struct notifier_block *head; }; +struct tunable_atomic_notifier_head { + spinlock_t lock; + struct notifier_block *head; + char *name; + struct kset *notifier_sub_kset; +}; + struct raw_notifier_head { struct notifier_block *head; }; @@ -73,6 +88,13 @@ struct srcu_notifier_head { struct notifier_block *head; }; +struct control_file_info { + struct tunable_atomic_notifier_head *nh; + struct tunable_atomic_notifier_block *n; + char *name; + struct control_file_info *next; +}; + #define ATOMIC_INIT_NOTIFIER_HEAD(name) do { \ spin_lock_init(&(name)->lock); \ (name)->head = NULL; \ @@ -81,6 +103,12 @@ struct srcu_notifier_head { init_rwsem(&(name)->rwsem); \ (name)->head = NULL; \ } while (0) +#define TUNABLE_ATOMIC_INIT_NOTIFIER(val1, val2) do { \ + spin_lock_init(&(val1)->lock); \ + (val1)->head = NULL; \ + (val1)->name = val2; \ + (val1)->notifier_sub_kset = NULL; \ + } while (0) #define RAW_INIT_NOTIFIER_HEAD(name) do { \ (name)->head = NULL; \ } while (0) @@ -96,6 +124,11 @@ extern void srcu_init_notifier_head(stru #define BLOCKING_NOTIFIER_INIT(name) { \ .rwsem = __RWSEM_INITIALIZER((name).rwsem), \ .head = NULL } +#define TUNABLE_ATOMIC_NOTIFIER_INIT(val1, val2) { \ + .lock =__SPIN_LOCK_UNLOCKED(val1.lock), \ + .head = NULL, \ + .name = val2, \ + .notifier_sub_kset = NULL } #define RAW_NOTIFIER_INIT(name) { \ .head = NULL } /* srcu_notifier_heads cannot be initialized statically */ @@ -106,6 +139,9 @@ extern void srcu_init_notifier_head(stru #define BLOCKING_NOTIFIER_HEAD(name) \ struct blocking_notifier_head name = \ BLOCKING_NOTIFIER_INIT(name) +#define TUNABLE_ATOMIC_NOTIFIER_HEAD(name, val) \ + struct tunable_atomic_notifier_head name = \ + TUNABLE_ATOMIC_NOTIFIER_INIT(name, val) #define RAW_NOTIFIER_HEAD(name) \ struct raw_notifier_head name = \ RAW_NOTIFIER_INIT(name) @@ -116,6 +152,10 @@ extern int atomic_notifier_chain_registe struct notifier_block *nb); extern int blocking_notifier_chain_register(struct blocking_notifier_head *nh, struct notifier_block *nb); +extern int tunable_atomic_notifier_chain_register( + struct tunable_atomic_notifier_head *nh, + struct tunable_atomic_notifier_block *nb, + char *name, char *desc); extern int raw_notifier_chain_register(struct raw_notifier_head *nh, struct notifier_block *nb); extern int srcu_notifier_chain_register(struct srcu_notifier_head *nh, @@ -129,6 +169,9 @@ extern int atomic_notifier_chain_unregis struct notifier_block *nb); extern int blocking_notifier_chain_unregister(struct blocking_notifier_head *nh, struct notifier_block *nb); +extern int tunable_atomic_notifier_chain_unregister( + struct tunable_atomic_notifier_head *nh, + struct tunable_atomic_notifier_block *nb); extern int raw_notifier_chain_unregister(struct raw_notifier_head *nh, struct notifier_block *nb); extern int srcu_notifier_chain_unregister(struct srcu_notifier_head *nh, @@ -142,6 +185,14 @@ extern int blocking_notifier_call_chain( unsigned long val, void *v); extern int __blocking_notifier_call_chain(struct blocking_notifier_head *nh, unsigned long val, void *v, int nr_to_call, int *nr_calls); +extern int tunable_atomic_notifier_call_chain( + struct tunable_atomic_notifier_head *nh, + unsigned long val, void *v); +extern int __tunable_atomic_notifier_call_chain( + struct tunable_atomic_notifier_head *nh, + unsigned long val, void *v, + int nr_to_call, int *nr_calls); +extern int tunable_atomic_notifier_init(void); extern int raw_notifier_call_chain(struct raw_notifier_head *nh, unsigned long val, void *v); extern int __raw_notifier_call_chain(struct raw_notifier_head *nh, diff -uprN linux-2.6.25-rc8-mm1.orig/kernel/ksysfs.c linux-2.6.25-rc8-mm1/kernel/ksysfs.c --- linux-2.6.25-rc8-mm1.orig/kernel/ksysfs.c 2008-04-02 04:44:26.000000000 +0900 +++ linux-2.6.25-rc8-mm1/kernel/ksysfs.c 2008-04-09 20:11:15.440000000 +0900 @@ -15,6 +15,7 @@ #include <linux/init.h> #include <linux/kexec.h> #include <linux/sched.h> +#include <linux/notifier.h> #define KERNEL_ATTR_RO(_name) \ static struct kobj_attribute _name##_attr = __ATTR_RO(_name) @@ -146,7 +147,10 @@ static int __init ksysfs_init(void) if (error) goto notes_exit; - return 0; + /* create the /sys/kernel/notifiers directory */ + error = tunable_atomic_notifier_init(); + + return error; notes_exit: if (notes_size > 0) diff -uprN linux-2.6.25-rc8-mm1.orig/kernel/notifier.c linux-2.6.25-rc8-mm1/kernel/notifier.c --- linux-2.6.25-rc8-mm1.orig/kernel/notifier.c 2008-04-08 16:37:44.904000000 +0900 +++ linux-2.6.25-rc8-mm1/kernel/notifier.c 2008-04-11 16:31:14.765088353 +0900 @@ -319,6 +319,261 @@ int blocking_notifier_call_chain(struct EXPORT_SYMBOL_GPL(blocking_notifier_call_chain); /* + * Tunable atomic notifier chain routines. Registration and unregistration + * use a spinlock, and call_chain is synchronized by RCU (no locks). + * User can change the list order to use /sys/kernel/notifiers/list-name/. + */ + +static ssize_t priority_show(struct kobject *kobj, + struct kobj_attribute *attr, const char *buf) +{ + struct tunable_atomic_notifier_block *n = container_of(kobj, + struct tunable_atomic_notifier_block, kobj); + + return sprintf(buf, "%d\n", n->nb->priority); +} + +static ssize_t priority_store(struct kobject *kobj, + struct kobj_attribute *attr, const char *buf, size_t size) +{ + struct tunable_atomic_notifier_block *n = container_of(kobj, + struct tunable_atomic_notifier_block, kobj); + struct tunable_atomic_notifier_head *nh = n->head; + unsigned long flags; + int priority, ret; + + sscanf(buf, "%d", &priority); + n->nb->priority = priority; + + spin_lock_irqsave(&nh->lock, flags); + ret = notifier_chain_unregister(&nh->head, n->nb); + if (ret) + goto out_unlock; + ret = notifier_chain_register(&nh->head, n->nb); + +out_unlock: + spin_unlock_irqrestore(&nh->lock, flags); + + return (ret ? ret : size); + +} + +static ssize_t description_show(struct kobject *kobj, + struct kobj_attribute *attr, const char *buf) +{ + struct tunable_atomic_notifier_block *n = container_of(kobj, + struct tunable_atomic_notifier_block, kobj); + + if (n->desc) + return sprintf(buf, "%s\n", n->desc); + + return sprintf(buf, "Description is not available\n"); +} + +static struct kobj_attribute priority_attr = + __ATTR(priority, 0644, priority_show, priority_store); +static struct kobj_attribute description_attr = + __ATTR_RO(description); + +static struct attribute *notifiers_attributes[] = { + &priority_attr.attr, &description_attr.attr, NULL +}; + +static struct kobj_type notifiers_ktype = { + .sysfs_ops = &kobj_sysfs_ops, + .default_attrs = notifiers_attributes, +}; + +static struct kobject *notifiers_kobj; +struct control_file_info *base; + +int notifiers_kobject_create(struct tunable_atomic_notifier_head *nh, + struct tunable_atomic_notifier_block *n, char *name) +{ + int error = -ENOMEM; + struct kobject *kobj = &n->kobj; + + if (!nh->notifier_sub_kset) { + nh->notifier_sub_kset = kset_create_and_add(nh->name, NULL, + notifiers_kobj); + if (!nh->notifier_sub_kset) + goto out; + } + + memset(kobj, 0, sizeof(struct kobject)); + kobj->kset = nh->notifier_sub_kset; + error = kobject_init_and_add(kobj, ¬ifiers_ktype, NULL, "%s", name); + if (error) + kobject_put(kobj); + +out: + return error; +} + +/** + * tunable_atomic_notifier_chain_register - Add notifier to an tunable notifier chain + * @nh: Pointer to head of the tunable notifier chain + * @n: New entry in notifier chain + * @name: Pointer to the name of the new notifier entry + * @desc: Pointer to the description of new entry + * + * Adds a notifier to an tunable notifier chain and makes control dir. + * This function must be called after kmem_cache_init(). + * + * Returns zero on success or %-ENODEV on failure. + */ + +int tunable_atomic_notifier_chain_register( + struct tunable_atomic_notifier_head *nh, + struct tunable_atomic_notifier_block *n, char *name, char *desc) +{ + unsigned long flags; + int ret; + + if (!name) + return -EINVAL; + if (desc) + n->desc = desc; + + if (!notifiers_kobj) { + struct control_file_info *temp, *new; + + temp = kmalloc(sizeof(struct control_file_info), GFP_ATOMIC); + if (!temp) + return -ENOMEM; + temp->nh = nh; + temp->n = n; + temp->name = name; + temp->next = NULL; + if (!base) + base = temp; + else { + new = base; + while (new->next) { + new = new->next; + } + new->next = temp; + } + goto regist; + } + + ret = notifiers_kobject_create(nh, n, name); + if (ret) + return ret; + +regist: + spin_lock_irqsave(&nh->lock, flags); + ret = notifier_chain_register(&nh->head, n->nb); + spin_unlock_irqrestore(&nh->lock, flags); + n->head = nh; + + return ret; +} +EXPORT_SYMBOL_GPL(tunable_atomic_notifier_chain_register); + +/** + * tunable_atomic_notifier_chain_unregister - Remove notifier from a tunable notifier chain + * @nh: Pointer to head of the tunable notifier chain + * @n: Entry to remove from notifier chain + * + * Removes a notifier from a tunable notifier chain. + * + * Retunrns zero on success or %-ENOENT on failure. + */ + +int tunable_atomic_notifier_chain_unregister( + struct tunable_atomic_notifier_head *nh, + struct tunable_atomic_notifier_block *n) +{ + unsigned long flags; + int ret; + + spin_lock_irqsave(&nh->lock, flags); + ret = notifier_chain_unregister(&nh->head, n->nb); + spin_unlock_irqrestore(&nh->lock, flags); + synchronize_rcu(); + + if (ret) + return ret; + + kobject_del(&n->kobj); + kobject_put(&n->kobj); + + return 0; +} +EXPORT_SYMBOL_GPL(tunable_atomic_notifier_chain_unregister); + +/** + * __tunable_atomic_notifier_call_chain - Call functions in a tunable notifier chain + * @nh: Pointer to head of the tunable notifier chain + * @val: Value passed unmodified to notifier function + * @v: Pointer passed unmodified to notifier function + * @nr_to_call: See the comment for notifier_call_chain + * @nr_calls: See the comment for notifier_call_chain + * + * Calls each function in a notifier chain in turn. The functions + * run in an atomic context, so they must not block. + * This routine uses RCU to synchronize with changes to the chain. + * + * If the return value of the notifier can be and'ed + * with %NOTIFY_STOP_MASK then tunable_atomic_notifier_call_chain() + * will return immediately, with the return value of + * the notifier function which halted execution. + * Otherwise the return value is the return value + * of the last notifier function called. + */ + +int __kprobes __tunable_atomic_notifier_call_chain( + struct tunable_atomic_notifier_head *nh, + unsigned long val, void *v, + int nr_to_call, int *nr_calls) +{ + int ret; + + rcu_read_lock(); + ret = notifier_call_chain(&nh->head, val, v, nr_to_call, nr_calls); + rcu_read_unlock(); + return ret; +} +EXPORT_SYMBOL_GPL(__tunable_atomic_notifier_call_chain); + +int __kprobes tunable_atomic_notifier_call_chain( + struct tunable_atomic_notifier_head *nh, + unsigned long val, void *v) +{ + return __tunable_atomic_notifier_call_chain(nh, val, v, -1, NULL); +} +EXPORT_SYMBOL_GPL(tunable_atomic_notifier_call_chain); + +int __init tunable_atomic_notifier_init(void) { + struct control_file_info *prev, *temp = base; + struct tunable_atomic_notifier_head *nh; + struct tunable_atomic_notifier_block *n; + char *name; + int error; + + notifiers_kobj = kobject_create_and_add("notifiers", kernel_kobj); + + if (!notifiers_kobj) + return -ENOMEM; + + while (temp) { + nh = temp->nh; + n = temp->n; + name = temp->name; + + error = notifiers_kobject_create(nh, n, name); + if (error) + printk("%s: %s is failed to create. err = %d\n", + nh->name, name, error); + prev = temp; + temp = temp->next; + kfree(prev); + } + return 0; +} + +/* * Raw notifier chain routines. There is no protection; * the caller must provide it. Use at your own risk! */ [-- Attachment #2: Type: text/plain, Size: 143 bytes --] _______________________________________________ kexec mailing list kexec@lists.infradead.org http://lists.infradead.org/mailman/listinfo/kexec ^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 1/2] add tunable_notifier function ,take2 @ 2008-04-11 7:53 ` Takenori Nagano 0 siblings, 0 replies; 14+ messages in thread From: Takenori Nagano @ 2008-04-11 7:53 UTC (permalink / raw) To: linux-kernel, Andrew Morton Cc: kdb, vgoyal, Eric W. Biederman, k-miyoshi, kexec, Bernhard Walle, Keith Owens, nickpiggin, Randy Dunlap, greg This patch adds new notifier function tunable_notifier_chain. Its base is atomic_notifier_chain. Thanks, --- Signed-off-by: Takenori Nagano <t-nagano@ah.jp.nec.com> --- diff -uprN linux-2.6.25-rc8-mm1.orig/include/linux/notifier.h linux-2.6.25-rc8-mm1/include/linux/notifier.h --- linux-2.6.25-rc8-mm1.orig/include/linux/notifier.h 2008-04-08 16:37:43.700000000 +0900 +++ linux-2.6.25-rc8-mm1/include/linux/notifier.h 2008-04-09 20:01:10.328000000 +0900 @@ -13,6 +13,7 @@ #include <linux/mutex.h> #include <linux/rwsem.h> #include <linux/srcu.h> +#include <linux/kobject.h> /* * Notifier chains are of four types: @@ -53,6 +54,13 @@ struct notifier_block { int priority; }; +struct tunable_atomic_notifier_block { + struct notifier_block *nb; + struct tunable_atomic_notifier_head *head; + struct kobject kobj; + char *desc; +}; + struct atomic_notifier_head { spinlock_t lock; struct notifier_block *head; @@ -63,6 +71,13 @@ struct blocking_notifier_head { struct notifier_block *head; }; +struct tunable_atomic_notifier_head { + spinlock_t lock; + struct notifier_block *head; + char *name; + struct kset *notifier_sub_kset; +}; + struct raw_notifier_head { struct notifier_block *head; }; @@ -73,6 +88,13 @@ struct srcu_notifier_head { struct notifier_block *head; }; +struct control_file_info { + struct tunable_atomic_notifier_head *nh; + struct tunable_atomic_notifier_block *n; + char *name; + struct control_file_info *next; +}; + #define ATOMIC_INIT_NOTIFIER_HEAD(name) do { \ spin_lock_init(&(name)->lock); \ (name)->head = NULL; \ @@ -81,6 +103,12 @@ struct srcu_notifier_head { init_rwsem(&(name)->rwsem); \ (name)->head = NULL; \ } while (0) +#define TUNABLE_ATOMIC_INIT_NOTIFIER(val1, val2) do { \ + spin_lock_init(&(val1)->lock); \ + (val1)->head = NULL; \ + (val1)->name = val2; \ + (val1)->notifier_sub_kset = NULL; \ + } while (0) #define RAW_INIT_NOTIFIER_HEAD(name) do { \ (name)->head = NULL; \ } while (0) @@ -96,6 +124,11 @@ extern void srcu_init_notifier_head(stru #define BLOCKING_NOTIFIER_INIT(name) { \ .rwsem = __RWSEM_INITIALIZER((name).rwsem), \ .head = NULL } +#define TUNABLE_ATOMIC_NOTIFIER_INIT(val1, val2) { \ + .lock =__SPIN_LOCK_UNLOCKED(val1.lock), \ + .head = NULL, \ + .name = val2, \ + .notifier_sub_kset = NULL } #define RAW_NOTIFIER_INIT(name) { \ .head = NULL } /* srcu_notifier_heads cannot be initialized statically */ @@ -106,6 +139,9 @@ extern void srcu_init_notifier_head(stru #define BLOCKING_NOTIFIER_HEAD(name) \ struct blocking_notifier_head name = \ BLOCKING_NOTIFIER_INIT(name) +#define TUNABLE_ATOMIC_NOTIFIER_HEAD(name, val) \ + struct tunable_atomic_notifier_head name = \ + TUNABLE_ATOMIC_NOTIFIER_INIT(name, val) #define RAW_NOTIFIER_HEAD(name) \ struct raw_notifier_head name = \ RAW_NOTIFIER_INIT(name) @@ -116,6 +152,10 @@ extern int atomic_notifier_chain_registe struct notifier_block *nb); extern int blocking_notifier_chain_register(struct blocking_notifier_head *nh, struct notifier_block *nb); +extern int tunable_atomic_notifier_chain_register( + struct tunable_atomic_notifier_head *nh, + struct tunable_atomic_notifier_block *nb, + char *name, char *desc); extern int raw_notifier_chain_register(struct raw_notifier_head *nh, struct notifier_block *nb); extern int srcu_notifier_chain_register(struct srcu_notifier_head *nh, @@ -129,6 +169,9 @@ extern int atomic_notifier_chain_unregis struct notifier_block *nb); extern int blocking_notifier_chain_unregister(struct blocking_notifier_head *nh, struct notifier_block *nb); +extern int tunable_atomic_notifier_chain_unregister( + struct tunable_atomic_notifier_head *nh, + struct tunable_atomic_notifier_block *nb); extern int raw_notifier_chain_unregister(struct raw_notifier_head *nh, struct notifier_block *nb); extern int srcu_notifier_chain_unregister(struct srcu_notifier_head *nh, @@ -142,6 +185,14 @@ extern int blocking_notifier_call_chain( unsigned long val, void *v); extern int __blocking_notifier_call_chain(struct blocking_notifier_head *nh, unsigned long val, void *v, int nr_to_call, int *nr_calls); +extern int tunable_atomic_notifier_call_chain( + struct tunable_atomic_notifier_head *nh, + unsigned long val, void *v); +extern int __tunable_atomic_notifier_call_chain( + struct tunable_atomic_notifier_head *nh, + unsigned long val, void *v, + int nr_to_call, int *nr_calls); +extern int tunable_atomic_notifier_init(void); extern int raw_notifier_call_chain(struct raw_notifier_head *nh, unsigned long val, void *v); extern int __raw_notifier_call_chain(struct raw_notifier_head *nh, diff -uprN linux-2.6.25-rc8-mm1.orig/kernel/ksysfs.c linux-2.6.25-rc8-mm1/kernel/ksysfs.c --- linux-2.6.25-rc8-mm1.orig/kernel/ksysfs.c 2008-04-02 04:44:26.000000000 +0900 +++ linux-2.6.25-rc8-mm1/kernel/ksysfs.c 2008-04-09 20:11:15.440000000 +0900 @@ -15,6 +15,7 @@ #include <linux/init.h> #include <linux/kexec.h> #include <linux/sched.h> +#include <linux/notifier.h> #define KERNEL_ATTR_RO(_name) \ static struct kobj_attribute _name##_attr = __ATTR_RO(_name) @@ -146,7 +147,10 @@ static int __init ksysfs_init(void) if (error) goto notes_exit; - return 0; + /* create the /sys/kernel/notifiers directory */ + error = tunable_atomic_notifier_init(); + + return error; notes_exit: if (notes_size > 0) diff -uprN linux-2.6.25-rc8-mm1.orig/kernel/notifier.c linux-2.6.25-rc8-mm1/kernel/notifier.c --- linux-2.6.25-rc8-mm1.orig/kernel/notifier.c 2008-04-08 16:37:44.904000000 +0900 +++ linux-2.6.25-rc8-mm1/kernel/notifier.c 2008-04-11 16:31:14.765088353 +0900 @@ -319,6 +319,261 @@ int blocking_notifier_call_chain(struct EXPORT_SYMBOL_GPL(blocking_notifier_call_chain); /* + * Tunable atomic notifier chain routines. Registration and unregistration + * use a spinlock, and call_chain is synchronized by RCU (no locks). + * User can change the list order to use /sys/kernel/notifiers/list-name/. + */ + +static ssize_t priority_show(struct kobject *kobj, + struct kobj_attribute *attr, const char *buf) +{ + struct tunable_atomic_notifier_block *n = container_of(kobj, + struct tunable_atomic_notifier_block, kobj); + + return sprintf(buf, "%d\n", n->nb->priority); +} + +static ssize_t priority_store(struct kobject *kobj, + struct kobj_attribute *attr, const char *buf, size_t size) +{ + struct tunable_atomic_notifier_block *n = container_of(kobj, + struct tunable_atomic_notifier_block, kobj); + struct tunable_atomic_notifier_head *nh = n->head; + unsigned long flags; + int priority, ret; + + sscanf(buf, "%d", &priority); + n->nb->priority = priority; + + spin_lock_irqsave(&nh->lock, flags); + ret = notifier_chain_unregister(&nh->head, n->nb); + if (ret) + goto out_unlock; + ret = notifier_chain_register(&nh->head, n->nb); + +out_unlock: + spin_unlock_irqrestore(&nh->lock, flags); + + return (ret ? ret : size); + +} + +static ssize_t description_show(struct kobject *kobj, + struct kobj_attribute *attr, const char *buf) +{ + struct tunable_atomic_notifier_block *n = container_of(kobj, + struct tunable_atomic_notifier_block, kobj); + + if (n->desc) + return sprintf(buf, "%s\n", n->desc); + + return sprintf(buf, "Description is not available\n"); +} + +static struct kobj_attribute priority_attr = + __ATTR(priority, 0644, priority_show, priority_store); +static struct kobj_attribute description_attr = + __ATTR_RO(description); + +static struct attribute *notifiers_attributes[] = { + &priority_attr.attr, &description_attr.attr, NULL +}; + +static struct kobj_type notifiers_ktype = { + .sysfs_ops = &kobj_sysfs_ops, + .default_attrs = notifiers_attributes, +}; + +static struct kobject *notifiers_kobj; +struct control_file_info *base; + +int notifiers_kobject_create(struct tunable_atomic_notifier_head *nh, + struct tunable_atomic_notifier_block *n, char *name) +{ + int error = -ENOMEM; + struct kobject *kobj = &n->kobj; + + if (!nh->notifier_sub_kset) { + nh->notifier_sub_kset = kset_create_and_add(nh->name, NULL, + notifiers_kobj); + if (!nh->notifier_sub_kset) + goto out; + } + + memset(kobj, 0, sizeof(struct kobject)); + kobj->kset = nh->notifier_sub_kset; + error = kobject_init_and_add(kobj, ¬ifiers_ktype, NULL, "%s", name); + if (error) + kobject_put(kobj); + +out: + return error; +} + +/** + * tunable_atomic_notifier_chain_register - Add notifier to an tunable notifier chain + * @nh: Pointer to head of the tunable notifier chain + * @n: New entry in notifier chain + * @name: Pointer to the name of the new notifier entry + * @desc: Pointer to the description of new entry + * + * Adds a notifier to an tunable notifier chain and makes control dir. + * This function must be called after kmem_cache_init(). + * + * Returns zero on success or %-ENODEV on failure. + */ + +int tunable_atomic_notifier_chain_register( + struct tunable_atomic_notifier_head *nh, + struct tunable_atomic_notifier_block *n, char *name, char *desc) +{ + unsigned long flags; + int ret; + + if (!name) + return -EINVAL; + if (desc) + n->desc = desc; + + if (!notifiers_kobj) { + struct control_file_info *temp, *new; + + temp = kmalloc(sizeof(struct control_file_info), GFP_ATOMIC); + if (!temp) + return -ENOMEM; + temp->nh = nh; + temp->n = n; + temp->name = name; + temp->next = NULL; + if (!base) + base = temp; + else { + new = base; + while (new->next) { + new = new->next; + } + new->next = temp; + } + goto regist; + } + + ret = notifiers_kobject_create(nh, n, name); + if (ret) + return ret; + +regist: + spin_lock_irqsave(&nh->lock, flags); + ret = notifier_chain_register(&nh->head, n->nb); + spin_unlock_irqrestore(&nh->lock, flags); + n->head = nh; + + return ret; +} +EXPORT_SYMBOL_GPL(tunable_atomic_notifier_chain_register); + +/** + * tunable_atomic_notifier_chain_unregister - Remove notifier from a tunable notifier chain + * @nh: Pointer to head of the tunable notifier chain + * @n: Entry to remove from notifier chain + * + * Removes a notifier from a tunable notifier chain. + * + * Retunrns zero on success or %-ENOENT on failure. + */ + +int tunable_atomic_notifier_chain_unregister( + struct tunable_atomic_notifier_head *nh, + struct tunable_atomic_notifier_block *n) +{ + unsigned long flags; + int ret; + + spin_lock_irqsave(&nh->lock, flags); + ret = notifier_chain_unregister(&nh->head, n->nb); + spin_unlock_irqrestore(&nh->lock, flags); + synchronize_rcu(); + + if (ret) + return ret; + + kobject_del(&n->kobj); + kobject_put(&n->kobj); + + return 0; +} +EXPORT_SYMBOL_GPL(tunable_atomic_notifier_chain_unregister); + +/** + * __tunable_atomic_notifier_call_chain - Call functions in a tunable notifier chain + * @nh: Pointer to head of the tunable notifier chain + * @val: Value passed unmodified to notifier function + * @v: Pointer passed unmodified to notifier function + * @nr_to_call: See the comment for notifier_call_chain + * @nr_calls: See the comment for notifier_call_chain + * + * Calls each function in a notifier chain in turn. The functions + * run in an atomic context, so they must not block. + * This routine uses RCU to synchronize with changes to the chain. + * + * If the return value of the notifier can be and'ed + * with %NOTIFY_STOP_MASK then tunable_atomic_notifier_call_chain() + * will return immediately, with the return value of + * the notifier function which halted execution. + * Otherwise the return value is the return value + * of the last notifier function called. + */ + +int __kprobes __tunable_atomic_notifier_call_chain( + struct tunable_atomic_notifier_head *nh, + unsigned long val, void *v, + int nr_to_call, int *nr_calls) +{ + int ret; + + rcu_read_lock(); + ret = notifier_call_chain(&nh->head, val, v, nr_to_call, nr_calls); + rcu_read_unlock(); + return ret; +} +EXPORT_SYMBOL_GPL(__tunable_atomic_notifier_call_chain); + +int __kprobes tunable_atomic_notifier_call_chain( + struct tunable_atomic_notifier_head *nh, + unsigned long val, void *v) +{ + return __tunable_atomic_notifier_call_chain(nh, val, v, -1, NULL); +} +EXPORT_SYMBOL_GPL(tunable_atomic_notifier_call_chain); + +int __init tunable_atomic_notifier_init(void) { + struct control_file_info *prev, *temp = base; + struct tunable_atomic_notifier_head *nh; + struct tunable_atomic_notifier_block *n; + char *name; + int error; + + notifiers_kobj = kobject_create_and_add("notifiers", kernel_kobj); + + if (!notifiers_kobj) + return -ENOMEM; + + while (temp) { + nh = temp->nh; + n = temp->n; + name = temp->name; + + error = notifiers_kobject_create(nh, n, name); + if (error) + printk("%s: %s is failed to create. err = %d\n", + nh->name, name, error); + prev = temp; + temp = temp->next; + kfree(prev); + } + return 0; +} + +/* * Raw notifier chain routines. There is no protection; * the caller must provide it. Use at your own risk! */ ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 1/2] add tunable_notifier function ,take2 2008-04-11 7:53 ` Takenori Nagano @ 2008-04-11 19:55 ` Greg KH -1 siblings, 0 replies; 14+ messages in thread From: Greg KH @ 2008-04-11 19:55 UTC (permalink / raw) To: Takenori Nagano Cc: nickpiggin, k-miyoshi, Bernhard Walle, kdb, kexec, linux-kernel, Randy Dunlap, vgoyal, Eric W. Biederman, Keith Owens, Andrew Morton On Fri, Apr 11, 2008 at 04:53:52PM +0900, Takenori Nagano wrote: > This patch adds new notifier function tunable_notifier_chain. Its base is > atomic_notifier_chain. You are adding sysfs files, not debugfs files, please change your announcement text. Also, as you are adding new sysfs files, we need some documentation to be added to Documentation/ABI/ describing what these files are, what are in them, and how to use them. thanks, greg k-h _______________________________________________ kexec mailing list kexec@lists.infradead.org http://lists.infradead.org/mailman/listinfo/kexec ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 1/2] add tunable_notifier function ,take2 @ 2008-04-11 19:55 ` Greg KH 0 siblings, 0 replies; 14+ messages in thread From: Greg KH @ 2008-04-11 19:55 UTC (permalink / raw) To: Takenori Nagano Cc: linux-kernel, Andrew Morton, kdb, vgoyal, Eric W. Biederman, k-miyoshi, kexec, Bernhard Walle, Keith Owens, nickpiggin, Randy Dunlap On Fri, Apr 11, 2008 at 04:53:52PM +0900, Takenori Nagano wrote: > This patch adds new notifier function tunable_notifier_chain. Its base is > atomic_notifier_chain. You are adding sysfs files, not debugfs files, please change your announcement text. Also, as you are adding new sysfs files, we need some documentation to be added to Documentation/ABI/ describing what these files are, what are in them, and how to use them. thanks, greg k-h ^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 2/2] implement new notifier function to panic_notifier_list ,take3 [not found] <47FF0EA5.8090804@ah.jp.nec.com> @ 2008-04-11 7:53 ` Takenori Nagano 2008-04-11 7:53 ` Takenori Nagano 1 sibling, 0 replies; 14+ messages in thread From: Takenori Nagano @ 2008-04-11 7:53 UTC (permalink / raw) To: linux-kernel, Andrew Morton Cc: nickpiggin, k-miyoshi, greg, Bernhard Walle, kdb, kexec, Randy Dunlap, vgoyal, Eric W. Biederman, Keith Owens [-- Attachment #1: Type: text/plain, Size: 23637 bytes --] This patch implements new notifier function to panic_notifier_list. We can change the list of order by debugfs. Thanks, --- Signed-off-by: Takenori Nagano <t-nagano@ah.jp.nec.com> --- diff -uprN linux-2.6.25-rc8-mm1.orig/arch/alpha/kernel/setup.c linux-2.6.25-rc8-mm1/arch/alpha/kernel/setup.c --- linux-2.6.25-rc8-mm1.orig/arch/alpha/kernel/setup.c 2008-04-02 04:44:26.000000000 +0900 +++ linux-2.6.25-rc8-mm1/arch/alpha/kernel/setup.c 2008-04-10 21:30:16.143555075 +0900 @@ -44,14 +44,18 @@ #include <asm/io.h> #include <linux/log2.h> -extern struct atomic_notifier_head panic_notifier_list; +extern struct tunable_atomic_notifier_head panic_notifier_list; static int alpha_panic_event(struct notifier_block *, unsigned long, void *); -static struct notifier_block alpha_panic_block = { +static struct notifier_block alpha_panic_block_base = { alpha_panic_event, NULL, INT_MAX /* try to do it first */ }; +static struct tunable_atomic_notifier_block alpha_panic_block = { + .nb = &alpha_panic_block_base +}; + #include <asm/uaccess.h> #include <asm/pgtable.h> #include <asm/system.h> @@ -521,8 +525,8 @@ setup_arch(char **cmdline_p) } /* Register a call for panic conditions. */ - atomic_notifier_chain_register(&panic_notifier_list, - &alpha_panic_block); + tunable_atomic_notifier_chain_register(&panic_notifier_list, + &alpha_panic_block, "alpha_panic", NULL); #ifdef CONFIG_ALPHA_GENERIC /* Assume that we've booted from SRM if we haven't booted from MILO. diff -uprN linux-2.6.25-rc8-mm1.orig/arch/arm/mach-omap1/board-voiceblue.c linux-2.6.25-rc8-mm1/arch/arm/mach-omap1/board-voiceblue.c --- linux-2.6.25-rc8-mm1.orig/arch/arm/mach-omap1/board-voiceblue.c 2008-04-02 04:44:26.000000000 +0900 +++ linux-2.6.25-rc8-mm1/arch/arm/mach-omap1/board-voiceblue.c 2008-04-10 22:01:58.275482847 +0900 @@ -226,14 +226,19 @@ static int panic_event(struct notifier_b return NOTIFY_DONE; } -static struct notifier_block panic_block = { +static struct notifier_block panic_block_base = { .notifier_call = panic_event, }; +static struct tunable_atomic_notifier_block panic_block = { + .nb = &panic_block_base +}; + static int __init voiceblue_setup(void) { /* Setup panic notifier */ - atomic_notifier_chain_register(&panic_notifier_list, &panic_block); + tunable_atomic_notifier_chain_register(&panic_notifier_list, + &panic_block, "VoiceBlue", NULL); return 0; } diff -uprN linux-2.6.25-rc8-mm1.orig/arch/mips/lasat/setup.c linux-2.6.25-rc8-mm1/arch/mips/lasat/setup.c --- linux-2.6.25-rc8-mm1.orig/arch/mips/lasat/setup.c 2008-04-02 04:44:26.000000000 +0900 +++ linux-2.6.25-rc8-mm1/arch/mips/lasat/setup.c 2008-04-10 21:10:23.147126270 +0900 @@ -106,7 +106,7 @@ static int lasat_panic_prom_monitor(stru return NOTIFY_DONE; } -static struct notifier_block lasat_panic_block[] = +static struct notifier_block lasat_panic_block_base[] = { { .notifier_call = lasat_panic_display, @@ -117,6 +117,18 @@ static struct notifier_block lasat_panic } }; +static struct tunable_atomic_notifier_block lasat_panic_block[] = { + { + .nb = &lasat_panic_block_base[0] + }, { + .nb = &lasat_panic_block_base[1] + } +}; + +static char* notifier_name[] = { + "lasat_panic_display", "lasat_panic_prom_monitor" +}; + void __init plat_time_init(void) { mips_hpt_frequency = lasat_board_info.li_cpu_hz / 2; @@ -134,8 +146,8 @@ void __init plat_mem_setup(void) /* Set up panic notifier */ for (i = 0; i < ARRAY_SIZE(lasat_panic_block); i++) - atomic_notifier_chain_register(&panic_notifier_list, - &lasat_panic_block[i]); + tunable_notifier_chain_register(&panic_notifier_list, + &lasat_panic_block[i], notifier_name[i], NULL); lasat_reboot_setup(); diff -uprN linux-2.6.25-rc8-mm1.orig/arch/mips/sgi-ip22/ip22-reset.c linux-2.6.25-rc8-mm1/arch/mips/sgi-ip22/ip22-reset.c --- linux-2.6.25-rc8-mm1.orig/arch/mips/sgi-ip22/ip22-reset.c 2008-04-02 04:44:26.000000000 +0900 +++ linux-2.6.25-rc8-mm1/arch/mips/sgi-ip22/ip22-reset.c 2008-04-10 22:04:16.570605171 +0900 @@ -226,10 +226,14 @@ static int panic_event(struct notifier_b return NOTIFY_DONE; } -static struct notifier_block panic_block = { +static struct notifier_block panic_block_base = { .notifier_call = panic_event, }; +static struct tunable_atomic_notifier_block panic_block = { + .nb = &panic_block_base +}; + static int __init reboot_setup(void) { int res; @@ -246,7 +250,8 @@ static int __init reboot_setup(void) init_timer(&blink_timer); blink_timer.function = blink_timeout; - atomic_notifier_chain_register(&panic_notifier_list, &panic_block); + tunable_atomic_notifier_chain_register(&panic_notifier_list, + &panic_block, "sgi-ip22", NULL); return 0; } diff -uprN linux-2.6.25-rc8-mm1.orig/arch/mips/sgi-ip32/ip32-reset.c linux-2.6.25-rc8-mm1/arch/mips/sgi-ip32/ip32-reset.c --- linux-2.6.25-rc8-mm1.orig/arch/mips/sgi-ip32/ip32-reset.c 2008-04-08 16:37:19.068000000 +0900 +++ linux-2.6.25-rc8-mm1/arch/mips/sgi-ip32/ip32-reset.c 2008-04-10 22:04:37.830470059 +0900 @@ -175,10 +175,14 @@ static int panic_event(struct notifier_b return NOTIFY_DONE; } -static struct notifier_block panic_block = { +static struct notifier_block panic_block_base = { .notifier_call = panic_event, }; +static struct tunable_atomic_notifier_block panic_block = { + .nb = &panic_block_base +}; + static __init int ip32_reboot_setup(void) { /* turn on the green led only */ @@ -193,7 +197,8 @@ static __init int ip32_reboot_setup(void init_timer(&blink_timer); blink_timer.function = blink_timeout; - atomic_notifier_chain_register(&panic_notifier_list, &panic_block); + tunable_atomic_notifier_chain_register(&panic_notifier_list, + &panic_block, "sgi-ip32", NULL); if (request_irq(MACEISA_RTC_IRQ, ip32_rtc_int, 0, "rtc", NULL)) panic("Can't allocate MACEISA RTC IRQ"); diff -uprN linux-2.6.25-rc8-mm1.orig/arch/parisc/kernel/pdc_chassis.c linux-2.6.25-rc8-mm1/arch/parisc/kernel/pdc_chassis.c --- linux-2.6.25-rc8-mm1.orig/arch/parisc/kernel/pdc_chassis.c 2008-04-02 04:44:26.000000000 +0900 +++ linux-2.6.25-rc8-mm1/arch/parisc/kernel/pdc_chassis.c 2008-04-10 21:28:22.068278645 +0900 @@ -101,11 +101,14 @@ static int pdc_chassis_panic_event(struc } -static struct notifier_block pdc_chassis_panic_block = { +static struct notifier_block pdc_chassis_panic_block_base = { .notifier_call = pdc_chassis_panic_event, .priority = INT_MAX, }; +static struct tunable_atomic_notifier_block pdc_chassis_panic_block = { + .nb = &pdc_chassis_panic_block_base +}; /** * parisc_reboot_event() - Called by the reboot handler. @@ -144,8 +147,8 @@ void __init parisc_pdc_chassis_init(void PDC_CHASSIS_VER); /* initialize panic notifier chain */ - atomic_notifier_chain_register(&panic_notifier_list, - &pdc_chassis_panic_block); + tunable_atomic_notifier_chain_register(&panic_notifier_list, + &pdc_chassis_panic_block, "pdc_chassis", NULL); /* initialize reboot notifier chain */ register_reboot_notifier(&pdc_chassis_reboot_block); diff -uprN linux-2.6.25-rc8-mm1.orig/arch/powerpc/kernel/setup-common.c linux-2.6.25-rc8-mm1/arch/powerpc/kernel/setup-common.c --- linux-2.6.25-rc8-mm1.orig/arch/powerpc/kernel/setup-common.c 2008-04-08 16:37:20.204000000 +0900 +++ linux-2.6.25-rc8-mm1/arch/powerpc/kernel/setup-common.c 2008-04-08 16:32:35.232000000 +0900 @@ -609,14 +609,19 @@ static int ppc_panic_event(struct notifi return NOTIFY_DONE; } -static struct notifier_block ppc_panic_block = { +static struct notifier_block ppc_panic_block_base = { .notifier_call = ppc_panic_event, .priority = INT_MIN /* may not return; must be done last */ }; +static struct tunable_atomic_notifier_block ppc_panic_block = { + .nb = &ppc_panic_block_base +}; + void __init setup_panic(void) { - atomic_notifier_chain_register(&panic_notifier_list, &ppc_panic_block); + tunable_atomic_notifier_chain_register(&panic_notifier_list, + &ppc_panic_block, "powerpc", NULL); } #ifdef CONFIG_CHECK_CACHE_COHERENCY diff -uprN linux-2.6.25-rc8-mm1.orig/arch/ppc/platforms/prep_setup.c linux-2.6.25-rc8-mm1/arch/ppc/platforms/prep_setup.c --- linux-2.6.25-rc8-mm1.orig/arch/ppc/platforms/prep_setup.c 2008-04-08 16:37:23.060000000 +0900 +++ linux-2.6.25-rc8-mm1/arch/ppc/platforms/prep_setup.c 2008-04-10 21:31:42.807004709 +0900 @@ -634,12 +634,16 @@ ibm_statusled_panic(struct notifier_bloc return NOTIFY_DONE; } -static struct notifier_block ibm_statusled_block = { +static struct notifier_block ibm_statusled_block_base = { ibm_statusled_panic, NULL, INT_MAX /* try to do it first */ }; +static struct tunable_atomic_notifier_block ibm_statusled_block = { + .nb = &ibm_statusled_block_base +}; + static void ibm_statusled_progress(char *s, unsigned short hex) { @@ -654,8 +658,9 @@ ibm_statusled_progress(char *s, unsigned hex = 0xfff; if (!notifier_installed) { ++notifier_installed; - atomic_notifier_chain_register(&panic_notifier_list, - &ibm_statusled_block); + tunable_atomic_notifier_chain_register( + &panic_notifier_list, &ibm_statusled_block, + "IBM_statusLED", NULL); } } else diff -uprN linux-2.6.25-rc8-mm1.orig/arch/s390/kernel/ipl.c linux-2.6.25-rc8-mm1/arch/s390/kernel/ipl.c --- linux-2.6.25-rc8-mm1.orig/arch/s390/kernel/ipl.c 2008-04-02 04:44:26.000000000 +0900 +++ linux-2.6.25-rc8-mm1/arch/s390/kernel/ipl.c 2008-04-08 16:32:35.232000000 +0900 @@ -1372,11 +1372,15 @@ static int on_panic_notify(struct notifi return NOTIFY_OK; } -static struct notifier_block on_panic_nb = { +static struct notifier_block on_panic_nb_base = { .notifier_call = on_panic_notify, .priority = 0, }; +static struct tunable_atomic_notifier_block on_panic_nb = { + .nb = &on_panic_nb_base +}; + void __init setup_ipl(void) { ipl_info.type = get_ipl_type(); @@ -1402,7 +1406,8 @@ void __init setup_ipl(void) /* We have no info to copy */ break; } - atomic_notifier_chain_register(&panic_notifier_list, &on_panic_nb); + tunable_atomic_notifier_chain_register(&panic_notifier_list, + &on_panic_nb, "s390_ipl", NULL); } void __init ipl_save_parameters(void) diff -uprN linux-2.6.25-rc8-mm1.orig/arch/sparc64/kernel/sstate.c linux-2.6.25-rc8-mm1/arch/sparc64/kernel/sstate.c --- linux-2.6.25-rc8-mm1.orig/arch/sparc64/kernel/sstate.c 2008-04-02 04:44:26.000000000 +0900 +++ linux-2.6.25-rc8-mm1/arch/sparc64/kernel/sstate.c 2008-04-10 21:32:20.798763557 +0900 @@ -82,11 +82,15 @@ static int sstate_panic_event(struct not return NOTIFY_DONE; } -static struct notifier_block sstate_panic_block = { +static struct notifier_block sstate_panic_block_base = { .notifier_call = sstate_panic_event, .priority = INT_MAX, }; +static struct tunable_atomic_notifier_block sstate_panic_block = { + .nb = &sstate_panic_block_base +}; + void __init sun4v_sstate_init(void) { unsigned long major, minor; @@ -99,6 +103,6 @@ void __init sun4v_sstate_init(void) hv_supports_soft_state = 1; prom_sun4v_guest_soft_state(); - atomic_notifier_chain_register(&panic_notifier_list, - &sstate_panic_block); + tunable_atomic_notifier_chain_register(&panic_notifier_list, + &sstate_panic_block, "sstate" ,NULL); } diff -uprN linux-2.6.25-rc8-mm1.orig/arch/um/drivers/mconsole_kern.c linux-2.6.25-rc8-mm1/arch/um/drivers/mconsole_kern.c --- linux-2.6.25-rc8-mm1.orig/arch/um/drivers/mconsole_kern.c 2008-04-02 04:44:26.000000000 +0900 +++ linux-2.6.25-rc8-mm1/arch/um/drivers/mconsole_kern.c 2008-04-08 16:32:35.236000000 +0900 @@ -920,16 +920,20 @@ static int notify_panic(struct notifier_ return 0; } -static struct notifier_block panic_exit_notifier = { +static struct notifier_block panic_exit_notifier_base = { .notifier_call = notify_panic, .next = NULL, .priority = 1 }; +static struct tunable_atomic_notifier_block panic_exit_notifier = { + .nb = &panic_exit_notifier_base +}; + static int add_notifier(void) { - atomic_notifier_chain_register(&panic_notifier_list, - &panic_exit_notifier); + tunable_atomic_notifier_chain_register(&panic_notifier_list, + &panic_exit_notifier, "mconsole", NULL); return 0; } diff -uprN linux-2.6.25-rc8-mm1.orig/arch/um/kernel/um_arch.c linux-2.6.25-rc8-mm1/arch/um/kernel/um_arch.c --- linux-2.6.25-rc8-mm1.orig/arch/um/kernel/um_arch.c 2008-04-08 16:37:25.004000000 +0900 +++ linux-2.6.25-rc8-mm1/arch/um/kernel/um_arch.c 2008-04-08 16:32:35.236000000 +0900 @@ -234,12 +234,16 @@ static int panic_exit(struct notifier_bl return 0; } -static struct notifier_block panic_exit_notifier = { +static struct notifier_block panic_exit_notifier_base = { .notifier_call = panic_exit, .next = NULL, .priority = 0 }; +static struct tunable_atomic_notifier_block panic_exit_notifier = { + .nb = &panic_exit_notifier_base +}; + /* Set during early boot */ unsigned long task_size; EXPORT_SYMBOL(task_size); @@ -357,8 +361,8 @@ int __init linux_main(int argc, char **a printf("Kernel virtual memory size shrunk to %lu bytes\n", virtmem_size); - atomic_notifier_chain_register(&panic_notifier_list, - &panic_exit_notifier); + tunable_atomic_notifier_chain_register(&panic_notifier_list, + &panic_exit_notifier, "um", NULL); uml_postsetup(); diff -uprN linux-2.6.25-rc8-mm1.orig/arch/x86/lguest/boot.c linux-2.6.25-rc8-mm1/arch/x86/lguest/boot.c --- linux-2.6.25-rc8-mm1.orig/arch/x86/lguest/boot.c 2008-04-02 04:44:26.000000000 +0900 +++ linux-2.6.25-rc8-mm1/arch/x86/lguest/boot.c 2008-04-08 16:32:35.236000000 +0900 @@ -820,17 +820,22 @@ static int lguest_panic(struct notifier_ return NOTIFY_DONE; } -static struct notifier_block paniced = { +static struct notifier_block paniced_base = { .notifier_call = lguest_panic }; +static struct tunable_atomic_notifier_block paniced = { + .nb = = &paniced_base +}; + /* Setting up memory is fairly easy. */ static __init char *lguest_memory_setup(void) { /* We do this here and not earlier because lockcheck used to barf if we * did it before start_kernel(). I think we fixed that, so it'd be * nice to move it back to lguest_init. Patch welcome... */ - atomic_notifier_chain_register(&panic_notifier_list, &paniced); + tunable_atomic_notifier_chain_register(&panic_notifier_list, &paniced, + "lguest", NULL); /* The Linux bootloader header contains an "e820" memory map: the * Launcher populated the first entry with our memory limit. */ diff -uprN linux-2.6.25-rc8-mm1.orig/arch/xtensa/platforms/iss/setup.c linux-2.6.25-rc8-mm1/arch/xtensa/platforms/iss/setup.c --- linux-2.6.25-rc8-mm1.orig/arch/xtensa/platforms/iss/setup.c 2008-04-02 04:44:26.000000000 +0900 +++ linux-2.6.25-rc8-mm1/arch/xtensa/platforms/iss/setup.c 2008-04-10 21:33:24.422359602 +0900 @@ -98,13 +98,18 @@ iss_panic_event(struct notifier_block *t return NOTIFY_DONE; } -static struct notifier_block iss_panic_block = { +static struct notifier_block iss_panic_block_base = { iss_panic_event, NULL, 0 }; +static struct tunable_atomic_notifier_block iss_panic_block = { + .nb = &iss_panic_block_base +}; + void __init platform_setup(char **p_cmdline) { - atomic_notifier_chain_register(&panic_notifier_list, &iss_panic_block); + tunable_atomic_notifier_chain_register(&panic_notifier_list, + &iss_panic_block, "iss_panic", NULL); } diff -uprN linux-2.6.25-rc8-mm1.orig/drivers/char/ipmi/ipmi_msghandler.c linux-2.6.25-rc8-mm1/drivers/char/ipmi/ipmi_msghandler.c --- linux-2.6.25-rc8-mm1.orig/drivers/char/ipmi/ipmi_msghandler.c 2008-04-08 16:37:33.228000000 +0900 +++ linux-2.6.25-rc8-mm1/drivers/char/ipmi/ipmi_msghandler.c 2008-04-08 16:32:35.240000000 +0900 @@ -4235,12 +4235,16 @@ static int panic_event(struct notifier_b return NOTIFY_DONE; } -static struct notifier_block panic_block = { +static struct notifier_block panic_block_base = { .notifier_call = panic_event, .next = NULL, .priority = 200 /* priority: INT_MAX >= x >= 0 */ }; +static struct tunable_atomic_notifier_block panic_block = { + .nb = &panic_block_base +}; + static int ipmi_init_msghandler(void) { int rv; @@ -4270,7 +4274,8 @@ static int ipmi_init_msghandler(void) setup_timer(&ipmi_timer, ipmi_timeout, 0); mod_timer(&ipmi_timer, jiffies + IPMI_TIMEOUT_JIFFIES); - atomic_notifier_chain_register(&panic_notifier_list, &panic_block); + tunable_atomic_notifier_chain_register(&panic_notifier_list, + &panic_block, "ipmi_msghandler", NULL); initialized = 1; @@ -4290,7 +4295,8 @@ static __exit void cleanup_ipmi(void) if (!initialized) return; - atomic_notifier_chain_unregister(&panic_notifier_list, &panic_block); + tunable_atomic_notifier_chain_unregister(&panic_notifier_list, + &panic_block); /* * This can't be called if any interfaces exist, so no worry diff -uprN linux-2.6.25-rc8-mm1.orig/drivers/char/ipmi/ipmi_watchdog.c linux-2.6.25-rc8-mm1/drivers/char/ipmi/ipmi_watchdog.c --- linux-2.6.25-rc8-mm1.orig/drivers/char/ipmi/ipmi_watchdog.c 2008-04-08 16:37:33.240000000 +0900 +++ linux-2.6.25-rc8-mm1/drivers/char/ipmi/ipmi_watchdog.c 2008-04-08 16:32:35.240000000 +0900 @@ -1157,12 +1157,15 @@ static int wdog_panic_handler(struct not return NOTIFY_OK; } -static struct notifier_block wdog_panic_notifier = { +static struct notifier_block wdog_panic_notifier_base = { .notifier_call = wdog_panic_handler, .next = NULL, .priority = 150 /* priority: INT_MAX >= x >= 0 */ }; +static struct tunable_atomic_notifier_block wdog_panic_notifier = { + .nb = &wdog_panic_notifier_base +}; static void ipmi_new_smi(int if_num, struct device *device) { @@ -1302,8 +1305,8 @@ static int __init ipmi_wdog_init(void) check_parms(); register_reboot_notifier(&wdog_reboot_notifier); - atomic_notifier_chain_register(&panic_notifier_list, - &wdog_panic_notifier); + tunable_atomic_notifier_chain_register(&panic_notifier_list, + &wdog_panic_notifier, "ipmi_wdog", NULL); rv = ipmi_smi_watcher_register(&smi_watcher); if (rv) { @@ -1311,8 +1314,8 @@ static int __init ipmi_wdog_init(void) if (nmi_handler_registered) unregister_die_notifier(&ipmi_nmi_handler); #endif - atomic_notifier_chain_unregister(&panic_notifier_list, - &wdog_panic_notifier); + tunable_atomic_notifier_chain_unregister(&panic_notifier_list, + &wdog_panic_notifier); unregister_reboot_notifier(&wdog_reboot_notifier); printk(KERN_WARNING PFX "can't register smi watcher\n"); return rv; @@ -1333,8 +1336,8 @@ static void __exit ipmi_wdog_exit(void) unregister_die_notifier(&ipmi_nmi_handler); #endif - atomic_notifier_chain_unregister(&panic_notifier_list, - &wdog_panic_notifier); + tunable_atomic_notifier_chain_unregister(&panic_notifier_list, + &wdog_panic_notifier); unregister_reboot_notifier(&wdog_reboot_notifier); } module_exit(ipmi_wdog_exit); diff -uprN linux-2.6.25-rc8-mm1.orig/drivers/misc/ibmasm/heartbeat.c linux-2.6.25-rc8-mm1/drivers/misc/ibmasm/heartbeat.c --- linux-2.6.25-rc8-mm1.orig/drivers/misc/ibmasm/heartbeat.c 2008-04-08 16:37:35.952000000 +0900 +++ linux-2.6.25-rc8-mm1/drivers/misc/ibmasm/heartbeat.c 2008-04-10 21:34:19.254011678 +0900 @@ -48,17 +48,22 @@ static int panic_happened(struct notifie return 0; } -static struct notifier_block panic_notifier = { panic_happened, NULL, 1 }; +static struct notifier_block panic_notifier_base = { panic_happened, NULL, 1 }; + +static struct tunable_atomic_notifier_block panic_notifier = { + .nb = &panic_notifier_base +}; void ibmasm_register_panic_notifier(void) { - atomic_notifier_chain_register(&panic_notifier_list, &panic_notifier); + tunable_atomic_notifier_chain_register(&panic_notifier_list, + &panic_notifier, "ibmasm", NULL); } void ibmasm_unregister_panic_notifier(void) { - atomic_notifier_chain_unregister(&panic_notifier_list, - &panic_notifier); + tunable_atomic_notifier_chain_unregister(&panic_notifier_list, + &panic_notifier); } diff -uprN linux-2.6.25-rc8-mm1.orig/drivers/parisc/power.c linux-2.6.25-rc8-mm1/drivers/parisc/power.c --- linux-2.6.25-rc8-mm1.orig/drivers/parisc/power.c 2008-04-02 04:44:26.000000000 +0900 +++ linux-2.6.25-rc8-mm1/drivers/parisc/power.c 2008-04-10 21:34:44.089854095 +0900 @@ -189,11 +189,14 @@ static int parisc_panic_event(struct not return NOTIFY_DONE; } -static struct notifier_block parisc_panic_block = { +static struct notifier_block parisc_panic_block_base = { .notifier_call = parisc_panic_event, .priority = INT_MAX, }; +static struct tunable_atomic_notifier_block parisc_panic_block = { + .nb = &parisc_panic_block_base +}; static int __init power_init(void) { @@ -231,8 +234,8 @@ static int __init power_init(void) } /* Register a call for panic conditions. */ - atomic_notifier_chain_register(&panic_notifier_list, - &parisc_panic_block); + tunable_atomic_notifier_chain_register(&panic_notifier_list, + &parisc_panic_block, "parisc_panic", NULL); return 0; } @@ -241,8 +244,8 @@ static void __exit power_exit(void) { kthread_stop(power_task); - atomic_notifier_chain_unregister(&panic_notifier_list, - &parisc_panic_block); + tunable_atomic_notifier_chain_unregister(&panic_notifier_list, + &parisc_panic_block); pdc_soft_power_button(0); } diff -uprN linux-2.6.25-rc8-mm1.orig/include/linux/kernel.h linux-2.6.25-rc8-mm1/include/linux/kernel.h --- linux-2.6.25-rc8-mm1.orig/include/linux/kernel.h 2008-04-08 16:37:43.508000000 +0900 +++ linux-2.6.25-rc8-mm1/include/linux/kernel.h 2008-04-08 16:32:35.244000000 +0900 @@ -129,7 +129,7 @@ extern int _cond_resched(void); (__x < 0) ? -__x : __x; \ }) -extern struct atomic_notifier_head panic_notifier_list; +extern struct tunable_atomic_notifier_head panic_notifier_list; extern long (*panic_blink)(long time); NORET_TYPE void panic(const char * fmt, ...) __attribute__ ((NORET_AND format (printf, 1, 2))) __cold; diff -uprN linux-2.6.25-rc8-mm1.orig/kernel/panic.c linux-2.6.25-rc8-mm1/kernel/panic.c --- linux-2.6.25-rc8-mm1.orig/kernel/panic.c 2008-04-08 16:37:44.916000000 +0900 +++ linux-2.6.25-rc8-mm1/kernel/panic.c 2008-04-08 16:32:35.248000000 +0900 @@ -30,7 +30,7 @@ static DEFINE_SPINLOCK(pause_on_oops_loc int panic_timeout; -ATOMIC_NOTIFIER_HEAD(panic_notifier_list); +TUNABLE_ATOMIC_NOTIFIER_HEAD(panic_notifier_list, "panic_notifier_list"); EXPORT_SYMBOL(panic_notifier_list); @@ -98,7 +98,7 @@ NORET_TYPE void panic(const char * fmt, smp_send_stop(); #endif - atomic_notifier_call_chain(&panic_notifier_list, 0, buf); + tunable_atomic_notifier_call_chain(&panic_notifier_list, 0, buf); if (!panic_blink) panic_blink = no_blink; diff -uprN linux-2.6.25-rc8-mm1.orig/kernel/softlockup.c linux-2.6.25-rc8-mm1/kernel/softlockup.c --- linux-2.6.25-rc8-mm1.orig/kernel/softlockup.c 2008-04-02 04:44:26.000000000 +0900 +++ linux-2.6.25-rc8-mm1/kernel/softlockup.c 2008-04-08 16:32:35.248000000 +0900 @@ -35,8 +35,12 @@ softlock_panic(struct notifier_block *th return NOTIFY_DONE; } -static struct notifier_block panic_block = { - .notifier_call = softlock_panic, +static struct notifier_block panic_block_base = { + .notifier_call = softlock_panic +}; + +static struct tunable_atomic_notifier_block panic_block = { + .nb = &panic_block_base }; /* @@ -310,5 +314,6 @@ __init void spawn_softlockup_task(void) cpu_callback(&cpu_nfb, CPU_ONLINE, cpu); register_cpu_notifier(&cpu_nfb); - atomic_notifier_chain_register(&panic_notifier_list, &panic_block); + tunable_atomic_notifier_chain_register(&panic_notifier_list, + &panic_block, "softlockup", NULL); } [-- Attachment #2: Type: text/plain, Size: 143 bytes --] _______________________________________________ kexec mailing list kexec@lists.infradead.org http://lists.infradead.org/mailman/listinfo/kexec ^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 2/2] implement new notifier function to panic_notifier_list ,take3 @ 2008-04-11 7:53 ` Takenori Nagano 0 siblings, 0 replies; 14+ messages in thread From: Takenori Nagano @ 2008-04-11 7:53 UTC (permalink / raw) To: linux-kernel, Andrew Morton Cc: kdb, vgoyal, Eric W. Biederman, k-miyoshi, kexec, Bernhard Walle, Keith Owens, nickpiggin, Randy Dunlap, greg This patch implements new notifier function to panic_notifier_list. We can change the list of order by debugfs. Thanks, --- Signed-off-by: Takenori Nagano <t-nagano@ah.jp.nec.com> --- diff -uprN linux-2.6.25-rc8-mm1.orig/arch/alpha/kernel/setup.c linux-2.6.25-rc8-mm1/arch/alpha/kernel/setup.c --- linux-2.6.25-rc8-mm1.orig/arch/alpha/kernel/setup.c 2008-04-02 04:44:26.000000000 +0900 +++ linux-2.6.25-rc8-mm1/arch/alpha/kernel/setup.c 2008-04-10 21:30:16.143555075 +0900 @@ -44,14 +44,18 @@ #include <asm/io.h> #include <linux/log2.h> -extern struct atomic_notifier_head panic_notifier_list; +extern struct tunable_atomic_notifier_head panic_notifier_list; static int alpha_panic_event(struct notifier_block *, unsigned long, void *); -static struct notifier_block alpha_panic_block = { +static struct notifier_block alpha_panic_block_base = { alpha_panic_event, NULL, INT_MAX /* try to do it first */ }; +static struct tunable_atomic_notifier_block alpha_panic_block = { + .nb = &alpha_panic_block_base +}; + #include <asm/uaccess.h> #include <asm/pgtable.h> #include <asm/system.h> @@ -521,8 +525,8 @@ setup_arch(char **cmdline_p) } /* Register a call for panic conditions. */ - atomic_notifier_chain_register(&panic_notifier_list, - &alpha_panic_block); + tunable_atomic_notifier_chain_register(&panic_notifier_list, + &alpha_panic_block, "alpha_panic", NULL); #ifdef CONFIG_ALPHA_GENERIC /* Assume that we've booted from SRM if we haven't booted from MILO. diff -uprN linux-2.6.25-rc8-mm1.orig/arch/arm/mach-omap1/board-voiceblue.c linux-2.6.25-rc8-mm1/arch/arm/mach-omap1/board-voiceblue.c --- linux-2.6.25-rc8-mm1.orig/arch/arm/mach-omap1/board-voiceblue.c 2008-04-02 04:44:26.000000000 +0900 +++ linux-2.6.25-rc8-mm1/arch/arm/mach-omap1/board-voiceblue.c 2008-04-10 22:01:58.275482847 +0900 @@ -226,14 +226,19 @@ static int panic_event(struct notifier_b return NOTIFY_DONE; } -static struct notifier_block panic_block = { +static struct notifier_block panic_block_base = { .notifier_call = panic_event, }; +static struct tunable_atomic_notifier_block panic_block = { + .nb = &panic_block_base +}; + static int __init voiceblue_setup(void) { /* Setup panic notifier */ - atomic_notifier_chain_register(&panic_notifier_list, &panic_block); + tunable_atomic_notifier_chain_register(&panic_notifier_list, + &panic_block, "VoiceBlue", NULL); return 0; } diff -uprN linux-2.6.25-rc8-mm1.orig/arch/mips/lasat/setup.c linux-2.6.25-rc8-mm1/arch/mips/lasat/setup.c --- linux-2.6.25-rc8-mm1.orig/arch/mips/lasat/setup.c 2008-04-02 04:44:26.000000000 +0900 +++ linux-2.6.25-rc8-mm1/arch/mips/lasat/setup.c 2008-04-10 21:10:23.147126270 +0900 @@ -106,7 +106,7 @@ static int lasat_panic_prom_monitor(stru return NOTIFY_DONE; } -static struct notifier_block lasat_panic_block[] = +static struct notifier_block lasat_panic_block_base[] = { { .notifier_call = lasat_panic_display, @@ -117,6 +117,18 @@ static struct notifier_block lasat_panic } }; +static struct tunable_atomic_notifier_block lasat_panic_block[] = { + { + .nb = &lasat_panic_block_base[0] + }, { + .nb = &lasat_panic_block_base[1] + } +}; + +static char* notifier_name[] = { + "lasat_panic_display", "lasat_panic_prom_monitor" +}; + void __init plat_time_init(void) { mips_hpt_frequency = lasat_board_info.li_cpu_hz / 2; @@ -134,8 +146,8 @@ void __init plat_mem_setup(void) /* Set up panic notifier */ for (i = 0; i < ARRAY_SIZE(lasat_panic_block); i++) - atomic_notifier_chain_register(&panic_notifier_list, - &lasat_panic_block[i]); + tunable_notifier_chain_register(&panic_notifier_list, + &lasat_panic_block[i], notifier_name[i], NULL); lasat_reboot_setup(); diff -uprN linux-2.6.25-rc8-mm1.orig/arch/mips/sgi-ip22/ip22-reset.c linux-2.6.25-rc8-mm1/arch/mips/sgi-ip22/ip22-reset.c --- linux-2.6.25-rc8-mm1.orig/arch/mips/sgi-ip22/ip22-reset.c 2008-04-02 04:44:26.000000000 +0900 +++ linux-2.6.25-rc8-mm1/arch/mips/sgi-ip22/ip22-reset.c 2008-04-10 22:04:16.570605171 +0900 @@ -226,10 +226,14 @@ static int panic_event(struct notifier_b return NOTIFY_DONE; } -static struct notifier_block panic_block = { +static struct notifier_block panic_block_base = { .notifier_call = panic_event, }; +static struct tunable_atomic_notifier_block panic_block = { + .nb = &panic_block_base +}; + static int __init reboot_setup(void) { int res; @@ -246,7 +250,8 @@ static int __init reboot_setup(void) init_timer(&blink_timer); blink_timer.function = blink_timeout; - atomic_notifier_chain_register(&panic_notifier_list, &panic_block); + tunable_atomic_notifier_chain_register(&panic_notifier_list, + &panic_block, "sgi-ip22", NULL); return 0; } diff -uprN linux-2.6.25-rc8-mm1.orig/arch/mips/sgi-ip32/ip32-reset.c linux-2.6.25-rc8-mm1/arch/mips/sgi-ip32/ip32-reset.c --- linux-2.6.25-rc8-mm1.orig/arch/mips/sgi-ip32/ip32-reset.c 2008-04-08 16:37:19.068000000 +0900 +++ linux-2.6.25-rc8-mm1/arch/mips/sgi-ip32/ip32-reset.c 2008-04-10 22:04:37.830470059 +0900 @@ -175,10 +175,14 @@ static int panic_event(struct notifier_b return NOTIFY_DONE; } -static struct notifier_block panic_block = { +static struct notifier_block panic_block_base = { .notifier_call = panic_event, }; +static struct tunable_atomic_notifier_block panic_block = { + .nb = &panic_block_base +}; + static __init int ip32_reboot_setup(void) { /* turn on the green led only */ @@ -193,7 +197,8 @@ static __init int ip32_reboot_setup(void init_timer(&blink_timer); blink_timer.function = blink_timeout; - atomic_notifier_chain_register(&panic_notifier_list, &panic_block); + tunable_atomic_notifier_chain_register(&panic_notifier_list, + &panic_block, "sgi-ip32", NULL); if (request_irq(MACEISA_RTC_IRQ, ip32_rtc_int, 0, "rtc", NULL)) panic("Can't allocate MACEISA RTC IRQ"); diff -uprN linux-2.6.25-rc8-mm1.orig/arch/parisc/kernel/pdc_chassis.c linux-2.6.25-rc8-mm1/arch/parisc/kernel/pdc_chassis.c --- linux-2.6.25-rc8-mm1.orig/arch/parisc/kernel/pdc_chassis.c 2008-04-02 04:44:26.000000000 +0900 +++ linux-2.6.25-rc8-mm1/arch/parisc/kernel/pdc_chassis.c 2008-04-10 21:28:22.068278645 +0900 @@ -101,11 +101,14 @@ static int pdc_chassis_panic_event(struc } -static struct notifier_block pdc_chassis_panic_block = { +static struct notifier_block pdc_chassis_panic_block_base = { .notifier_call = pdc_chassis_panic_event, .priority = INT_MAX, }; +static struct tunable_atomic_notifier_block pdc_chassis_panic_block = { + .nb = &pdc_chassis_panic_block_base +}; /** * parisc_reboot_event() - Called by the reboot handler. @@ -144,8 +147,8 @@ void __init parisc_pdc_chassis_init(void PDC_CHASSIS_VER); /* initialize panic notifier chain */ - atomic_notifier_chain_register(&panic_notifier_list, - &pdc_chassis_panic_block); + tunable_atomic_notifier_chain_register(&panic_notifier_list, + &pdc_chassis_panic_block, "pdc_chassis", NULL); /* initialize reboot notifier chain */ register_reboot_notifier(&pdc_chassis_reboot_block); diff -uprN linux-2.6.25-rc8-mm1.orig/arch/powerpc/kernel/setup-common.c linux-2.6.25-rc8-mm1/arch/powerpc/kernel/setup-common.c --- linux-2.6.25-rc8-mm1.orig/arch/powerpc/kernel/setup-common.c 2008-04-08 16:37:20.204000000 +0900 +++ linux-2.6.25-rc8-mm1/arch/powerpc/kernel/setup-common.c 2008-04-08 16:32:35.232000000 +0900 @@ -609,14 +609,19 @@ static int ppc_panic_event(struct notifi return NOTIFY_DONE; } -static struct notifier_block ppc_panic_block = { +static struct notifier_block ppc_panic_block_base = { .notifier_call = ppc_panic_event, .priority = INT_MIN /* may not return; must be done last */ }; +static struct tunable_atomic_notifier_block ppc_panic_block = { + .nb = &ppc_panic_block_base +}; + void __init setup_panic(void) { - atomic_notifier_chain_register(&panic_notifier_list, &ppc_panic_block); + tunable_atomic_notifier_chain_register(&panic_notifier_list, + &ppc_panic_block, "powerpc", NULL); } #ifdef CONFIG_CHECK_CACHE_COHERENCY diff -uprN linux-2.6.25-rc8-mm1.orig/arch/ppc/platforms/prep_setup.c linux-2.6.25-rc8-mm1/arch/ppc/platforms/prep_setup.c --- linux-2.6.25-rc8-mm1.orig/arch/ppc/platforms/prep_setup.c 2008-04-08 16:37:23.060000000 +0900 +++ linux-2.6.25-rc8-mm1/arch/ppc/platforms/prep_setup.c 2008-04-10 21:31:42.807004709 +0900 @@ -634,12 +634,16 @@ ibm_statusled_panic(struct notifier_bloc return NOTIFY_DONE; } -static struct notifier_block ibm_statusled_block = { +static struct notifier_block ibm_statusled_block_base = { ibm_statusled_panic, NULL, INT_MAX /* try to do it first */ }; +static struct tunable_atomic_notifier_block ibm_statusled_block = { + .nb = &ibm_statusled_block_base +}; + static void ibm_statusled_progress(char *s, unsigned short hex) { @@ -654,8 +658,9 @@ ibm_statusled_progress(char *s, unsigned hex = 0xfff; if (!notifier_installed) { ++notifier_installed; - atomic_notifier_chain_register(&panic_notifier_list, - &ibm_statusled_block); + tunable_atomic_notifier_chain_register( + &panic_notifier_list, &ibm_statusled_block, + "IBM_statusLED", NULL); } } else diff -uprN linux-2.6.25-rc8-mm1.orig/arch/s390/kernel/ipl.c linux-2.6.25-rc8-mm1/arch/s390/kernel/ipl.c --- linux-2.6.25-rc8-mm1.orig/arch/s390/kernel/ipl.c 2008-04-02 04:44:26.000000000 +0900 +++ linux-2.6.25-rc8-mm1/arch/s390/kernel/ipl.c 2008-04-08 16:32:35.232000000 +0900 @@ -1372,11 +1372,15 @@ static int on_panic_notify(struct notifi return NOTIFY_OK; } -static struct notifier_block on_panic_nb = { +static struct notifier_block on_panic_nb_base = { .notifier_call = on_panic_notify, .priority = 0, }; +static struct tunable_atomic_notifier_block on_panic_nb = { + .nb = &on_panic_nb_base +}; + void __init setup_ipl(void) { ipl_info.type = get_ipl_type(); @@ -1402,7 +1406,8 @@ void __init setup_ipl(void) /* We have no info to copy */ break; } - atomic_notifier_chain_register(&panic_notifier_list, &on_panic_nb); + tunable_atomic_notifier_chain_register(&panic_notifier_list, + &on_panic_nb, "s390_ipl", NULL); } void __init ipl_save_parameters(void) diff -uprN linux-2.6.25-rc8-mm1.orig/arch/sparc64/kernel/sstate.c linux-2.6.25-rc8-mm1/arch/sparc64/kernel/sstate.c --- linux-2.6.25-rc8-mm1.orig/arch/sparc64/kernel/sstate.c 2008-04-02 04:44:26.000000000 +0900 +++ linux-2.6.25-rc8-mm1/arch/sparc64/kernel/sstate.c 2008-04-10 21:32:20.798763557 +0900 @@ -82,11 +82,15 @@ static int sstate_panic_event(struct not return NOTIFY_DONE; } -static struct notifier_block sstate_panic_block = { +static struct notifier_block sstate_panic_block_base = { .notifier_call = sstate_panic_event, .priority = INT_MAX, }; +static struct tunable_atomic_notifier_block sstate_panic_block = { + .nb = &sstate_panic_block_base +}; + void __init sun4v_sstate_init(void) { unsigned long major, minor; @@ -99,6 +103,6 @@ void __init sun4v_sstate_init(void) hv_supports_soft_state = 1; prom_sun4v_guest_soft_state(); - atomic_notifier_chain_register(&panic_notifier_list, - &sstate_panic_block); + tunable_atomic_notifier_chain_register(&panic_notifier_list, + &sstate_panic_block, "sstate" ,NULL); } diff -uprN linux-2.6.25-rc8-mm1.orig/arch/um/drivers/mconsole_kern.c linux-2.6.25-rc8-mm1/arch/um/drivers/mconsole_kern.c --- linux-2.6.25-rc8-mm1.orig/arch/um/drivers/mconsole_kern.c 2008-04-02 04:44:26.000000000 +0900 +++ linux-2.6.25-rc8-mm1/arch/um/drivers/mconsole_kern.c 2008-04-08 16:32:35.236000000 +0900 @@ -920,16 +920,20 @@ static int notify_panic(struct notifier_ return 0; } -static struct notifier_block panic_exit_notifier = { +static struct notifier_block panic_exit_notifier_base = { .notifier_call = notify_panic, .next = NULL, .priority = 1 }; +static struct tunable_atomic_notifier_block panic_exit_notifier = { + .nb = &panic_exit_notifier_base +}; + static int add_notifier(void) { - atomic_notifier_chain_register(&panic_notifier_list, - &panic_exit_notifier); + tunable_atomic_notifier_chain_register(&panic_notifier_list, + &panic_exit_notifier, "mconsole", NULL); return 0; } diff -uprN linux-2.6.25-rc8-mm1.orig/arch/um/kernel/um_arch.c linux-2.6.25-rc8-mm1/arch/um/kernel/um_arch.c --- linux-2.6.25-rc8-mm1.orig/arch/um/kernel/um_arch.c 2008-04-08 16:37:25.004000000 +0900 +++ linux-2.6.25-rc8-mm1/arch/um/kernel/um_arch.c 2008-04-08 16:32:35.236000000 +0900 @@ -234,12 +234,16 @@ static int panic_exit(struct notifier_bl return 0; } -static struct notifier_block panic_exit_notifier = { +static struct notifier_block panic_exit_notifier_base = { .notifier_call = panic_exit, .next = NULL, .priority = 0 }; +static struct tunable_atomic_notifier_block panic_exit_notifier = { + .nb = &panic_exit_notifier_base +}; + /* Set during early boot */ unsigned long task_size; EXPORT_SYMBOL(task_size); @@ -357,8 +361,8 @@ int __init linux_main(int argc, char **a printf("Kernel virtual memory size shrunk to %lu bytes\n", virtmem_size); - atomic_notifier_chain_register(&panic_notifier_list, - &panic_exit_notifier); + tunable_atomic_notifier_chain_register(&panic_notifier_list, + &panic_exit_notifier, "um", NULL); uml_postsetup(); diff -uprN linux-2.6.25-rc8-mm1.orig/arch/x86/lguest/boot.c linux-2.6.25-rc8-mm1/arch/x86/lguest/boot.c --- linux-2.6.25-rc8-mm1.orig/arch/x86/lguest/boot.c 2008-04-02 04:44:26.000000000 +0900 +++ linux-2.6.25-rc8-mm1/arch/x86/lguest/boot.c 2008-04-08 16:32:35.236000000 +0900 @@ -820,17 +820,22 @@ static int lguest_panic(struct notifier_ return NOTIFY_DONE; } -static struct notifier_block paniced = { +static struct notifier_block paniced_base = { .notifier_call = lguest_panic }; +static struct tunable_atomic_notifier_block paniced = { + .nb = = &paniced_base +}; + /* Setting up memory is fairly easy. */ static __init char *lguest_memory_setup(void) { /* We do this here and not earlier because lockcheck used to barf if we * did it before start_kernel(). I think we fixed that, so it'd be * nice to move it back to lguest_init. Patch welcome... */ - atomic_notifier_chain_register(&panic_notifier_list, &paniced); + tunable_atomic_notifier_chain_register(&panic_notifier_list, &paniced, + "lguest", NULL); /* The Linux bootloader header contains an "e820" memory map: the * Launcher populated the first entry with our memory limit. */ diff -uprN linux-2.6.25-rc8-mm1.orig/arch/xtensa/platforms/iss/setup.c linux-2.6.25-rc8-mm1/arch/xtensa/platforms/iss/setup.c --- linux-2.6.25-rc8-mm1.orig/arch/xtensa/platforms/iss/setup.c 2008-04-02 04:44:26.000000000 +0900 +++ linux-2.6.25-rc8-mm1/arch/xtensa/platforms/iss/setup.c 2008-04-10 21:33:24.422359602 +0900 @@ -98,13 +98,18 @@ iss_panic_event(struct notifier_block *t return NOTIFY_DONE; } -static struct notifier_block iss_panic_block = { +static struct notifier_block iss_panic_block_base = { iss_panic_event, NULL, 0 }; +static struct tunable_atomic_notifier_block iss_panic_block = { + .nb = &iss_panic_block_base +}; + void __init platform_setup(char **p_cmdline) { - atomic_notifier_chain_register(&panic_notifier_list, &iss_panic_block); + tunable_atomic_notifier_chain_register(&panic_notifier_list, + &iss_panic_block, "iss_panic", NULL); } diff -uprN linux-2.6.25-rc8-mm1.orig/drivers/char/ipmi/ipmi_msghandler.c linux-2.6.25-rc8-mm1/drivers/char/ipmi/ipmi_msghandler.c --- linux-2.6.25-rc8-mm1.orig/drivers/char/ipmi/ipmi_msghandler.c 2008-04-08 16:37:33.228000000 +0900 +++ linux-2.6.25-rc8-mm1/drivers/char/ipmi/ipmi_msghandler.c 2008-04-08 16:32:35.240000000 +0900 @@ -4235,12 +4235,16 @@ static int panic_event(struct notifier_b return NOTIFY_DONE; } -static struct notifier_block panic_block = { +static struct notifier_block panic_block_base = { .notifier_call = panic_event, .next = NULL, .priority = 200 /* priority: INT_MAX >= x >= 0 */ }; +static struct tunable_atomic_notifier_block panic_block = { + .nb = &panic_block_base +}; + static int ipmi_init_msghandler(void) { int rv; @@ -4270,7 +4274,8 @@ static int ipmi_init_msghandler(void) setup_timer(&ipmi_timer, ipmi_timeout, 0); mod_timer(&ipmi_timer, jiffies + IPMI_TIMEOUT_JIFFIES); - atomic_notifier_chain_register(&panic_notifier_list, &panic_block); + tunable_atomic_notifier_chain_register(&panic_notifier_list, + &panic_block, "ipmi_msghandler", NULL); initialized = 1; @@ -4290,7 +4295,8 @@ static __exit void cleanup_ipmi(void) if (!initialized) return; - atomic_notifier_chain_unregister(&panic_notifier_list, &panic_block); + tunable_atomic_notifier_chain_unregister(&panic_notifier_list, + &panic_block); /* * This can't be called if any interfaces exist, so no worry diff -uprN linux-2.6.25-rc8-mm1.orig/drivers/char/ipmi/ipmi_watchdog.c linux-2.6.25-rc8-mm1/drivers/char/ipmi/ipmi_watchdog.c --- linux-2.6.25-rc8-mm1.orig/drivers/char/ipmi/ipmi_watchdog.c 2008-04-08 16:37:33.240000000 +0900 +++ linux-2.6.25-rc8-mm1/drivers/char/ipmi/ipmi_watchdog.c 2008-04-08 16:32:35.240000000 +0900 @@ -1157,12 +1157,15 @@ static int wdog_panic_handler(struct not return NOTIFY_OK; } -static struct notifier_block wdog_panic_notifier = { +static struct notifier_block wdog_panic_notifier_base = { .notifier_call = wdog_panic_handler, .next = NULL, .priority = 150 /* priority: INT_MAX >= x >= 0 */ }; +static struct tunable_atomic_notifier_block wdog_panic_notifier = { + .nb = &wdog_panic_notifier_base +}; static void ipmi_new_smi(int if_num, struct device *device) { @@ -1302,8 +1305,8 @@ static int __init ipmi_wdog_init(void) check_parms(); register_reboot_notifier(&wdog_reboot_notifier); - atomic_notifier_chain_register(&panic_notifier_list, - &wdog_panic_notifier); + tunable_atomic_notifier_chain_register(&panic_notifier_list, + &wdog_panic_notifier, "ipmi_wdog", NULL); rv = ipmi_smi_watcher_register(&smi_watcher); if (rv) { @@ -1311,8 +1314,8 @@ static int __init ipmi_wdog_init(void) if (nmi_handler_registered) unregister_die_notifier(&ipmi_nmi_handler); #endif - atomic_notifier_chain_unregister(&panic_notifier_list, - &wdog_panic_notifier); + tunable_atomic_notifier_chain_unregister(&panic_notifier_list, + &wdog_panic_notifier); unregister_reboot_notifier(&wdog_reboot_notifier); printk(KERN_WARNING PFX "can't register smi watcher\n"); return rv; @@ -1333,8 +1336,8 @@ static void __exit ipmi_wdog_exit(void) unregister_die_notifier(&ipmi_nmi_handler); #endif - atomic_notifier_chain_unregister(&panic_notifier_list, - &wdog_panic_notifier); + tunable_atomic_notifier_chain_unregister(&panic_notifier_list, + &wdog_panic_notifier); unregister_reboot_notifier(&wdog_reboot_notifier); } module_exit(ipmi_wdog_exit); diff -uprN linux-2.6.25-rc8-mm1.orig/drivers/misc/ibmasm/heartbeat.c linux-2.6.25-rc8-mm1/drivers/misc/ibmasm/heartbeat.c --- linux-2.6.25-rc8-mm1.orig/drivers/misc/ibmasm/heartbeat.c 2008-04-08 16:37:35.952000000 +0900 +++ linux-2.6.25-rc8-mm1/drivers/misc/ibmasm/heartbeat.c 2008-04-10 21:34:19.254011678 +0900 @@ -48,17 +48,22 @@ static int panic_happened(struct notifie return 0; } -static struct notifier_block panic_notifier = { panic_happened, NULL, 1 }; +static struct notifier_block panic_notifier_base = { panic_happened, NULL, 1 }; + +static struct tunable_atomic_notifier_block panic_notifier = { + .nb = &panic_notifier_base +}; void ibmasm_register_panic_notifier(void) { - atomic_notifier_chain_register(&panic_notifier_list, &panic_notifier); + tunable_atomic_notifier_chain_register(&panic_notifier_list, + &panic_notifier, "ibmasm", NULL); } void ibmasm_unregister_panic_notifier(void) { - atomic_notifier_chain_unregister(&panic_notifier_list, - &panic_notifier); + tunable_atomic_notifier_chain_unregister(&panic_notifier_list, + &panic_notifier); } diff -uprN linux-2.6.25-rc8-mm1.orig/drivers/parisc/power.c linux-2.6.25-rc8-mm1/drivers/parisc/power.c --- linux-2.6.25-rc8-mm1.orig/drivers/parisc/power.c 2008-04-02 04:44:26.000000000 +0900 +++ linux-2.6.25-rc8-mm1/drivers/parisc/power.c 2008-04-10 21:34:44.089854095 +0900 @@ -189,11 +189,14 @@ static int parisc_panic_event(struct not return NOTIFY_DONE; } -static struct notifier_block parisc_panic_block = { +static struct notifier_block parisc_panic_block_base = { .notifier_call = parisc_panic_event, .priority = INT_MAX, }; +static struct tunable_atomic_notifier_block parisc_panic_block = { + .nb = &parisc_panic_block_base +}; static int __init power_init(void) { @@ -231,8 +234,8 @@ static int __init power_init(void) } /* Register a call for panic conditions. */ - atomic_notifier_chain_register(&panic_notifier_list, - &parisc_panic_block); + tunable_atomic_notifier_chain_register(&panic_notifier_list, + &parisc_panic_block, "parisc_panic", NULL); return 0; } @@ -241,8 +244,8 @@ static void __exit power_exit(void) { kthread_stop(power_task); - atomic_notifier_chain_unregister(&panic_notifier_list, - &parisc_panic_block); + tunable_atomic_notifier_chain_unregister(&panic_notifier_list, + &parisc_panic_block); pdc_soft_power_button(0); } diff -uprN linux-2.6.25-rc8-mm1.orig/include/linux/kernel.h linux-2.6.25-rc8-mm1/include/linux/kernel.h --- linux-2.6.25-rc8-mm1.orig/include/linux/kernel.h 2008-04-08 16:37:43.508000000 +0900 +++ linux-2.6.25-rc8-mm1/include/linux/kernel.h 2008-04-08 16:32:35.244000000 +0900 @@ -129,7 +129,7 @@ extern int _cond_resched(void); (__x < 0) ? -__x : __x; \ }) -extern struct atomic_notifier_head panic_notifier_list; +extern struct tunable_atomic_notifier_head panic_notifier_list; extern long (*panic_blink)(long time); NORET_TYPE void panic(const char * fmt, ...) __attribute__ ((NORET_AND format (printf, 1, 2))) __cold; diff -uprN linux-2.6.25-rc8-mm1.orig/kernel/panic.c linux-2.6.25-rc8-mm1/kernel/panic.c --- linux-2.6.25-rc8-mm1.orig/kernel/panic.c 2008-04-08 16:37:44.916000000 +0900 +++ linux-2.6.25-rc8-mm1/kernel/panic.c 2008-04-08 16:32:35.248000000 +0900 @@ -30,7 +30,7 @@ static DEFINE_SPINLOCK(pause_on_oops_loc int panic_timeout; -ATOMIC_NOTIFIER_HEAD(panic_notifier_list); +TUNABLE_ATOMIC_NOTIFIER_HEAD(panic_notifier_list, "panic_notifier_list"); EXPORT_SYMBOL(panic_notifier_list); @@ -98,7 +98,7 @@ NORET_TYPE void panic(const char * fmt, smp_send_stop(); #endif - atomic_notifier_call_chain(&panic_notifier_list, 0, buf); + tunable_atomic_notifier_call_chain(&panic_notifier_list, 0, buf); if (!panic_blink) panic_blink = no_blink; diff -uprN linux-2.6.25-rc8-mm1.orig/kernel/softlockup.c linux-2.6.25-rc8-mm1/kernel/softlockup.c --- linux-2.6.25-rc8-mm1.orig/kernel/softlockup.c 2008-04-02 04:44:26.000000000 +0900 +++ linux-2.6.25-rc8-mm1/kernel/softlockup.c 2008-04-08 16:32:35.248000000 +0900 @@ -35,8 +35,12 @@ softlock_panic(struct notifier_block *th return NOTIFY_DONE; } -static struct notifier_block panic_block = { - .notifier_call = softlock_panic, +static struct notifier_block panic_block_base = { + .notifier_call = softlock_panic +}; + +static struct tunable_atomic_notifier_block panic_block = { + .nb = &panic_block_base }; /* @@ -310,5 +314,6 @@ __init void spawn_softlockup_task(void) cpu_callback(&cpu_nfb, CPU_ONLINE, cpu); register_cpu_notifier(&cpu_nfb); - atomic_notifier_chain_register(&panic_notifier_list, &panic_block); + tunable_atomic_notifier_chain_register(&panic_notifier_list, + &panic_block, "softlockup", NULL); } ^ permalink raw reply [flat|nested] 14+ messages in thread
[parent not found: <4716FFDB.7090502@ah.jp.nec.com>]
* [PATCH 1/2] add tunable_notifier function ,take2 [not found] <4716FFDB.7090502@ah.jp.nec.com> @ 2007-10-18 6:45 ` Takenori Nagano 2007-10-18 8:53 ` Takenori Nagano 1 sibling, 0 replies; 14+ messages in thread From: Takenori Nagano @ 2007-10-18 6:45 UTC (permalink / raw) To: linux-kernel Cc: k-miyoshi, Bernhard Walle, kdb, kexec, vgoyal, Eric W. Biederman, Keith Owens, Andrew Morton This patch adds new notifier function tunable_notifier_chain. Its base is atomic_notifier_chain. Thanks, --- Signed-off-by: Takenori Nagano <t-nagano@ah.jp.nec.com> --- diff -uprN linux-2.6.23.orig/include/linux/notifier.h linux-2.6.23/include/linux/notifier.h --- linux-2.6.23.orig/include/linux/notifier.h 2007-10-10 05:31:38.000000000 +0900 +++ linux-2.6.23/include/linux/notifier.h 2007-10-18 09:59:13.732000000 +0900 @@ -13,6 +13,7 @@ #include <linux/mutex.h> #include <linux/rwsem.h> #include <linux/srcu.h> +#include <linux/kobject.h> /* * Notifier chains are of four types: @@ -53,6 +54,14 @@ struct notifier_block { int priority; }; +struct tunable_atomic_notifier_block { + struct notifier_block *nb; + struct tunable_atomic_notifier_head *head; + struct dentry *dir; + struct dentry *pri_dentry; + struct dentry *desc_dentry; +}; + struct atomic_notifier_head { spinlock_t lock; struct notifier_block *head; @@ -63,6 +72,13 @@ struct blocking_notifier_head { struct notifier_block *head; }; +struct tunable_atomic_notifier_head { + spinlock_t lock; + struct notifier_block *head; + char *name; + struct dentry *dir; +}; + struct raw_notifier_head { struct notifier_block *head; }; @@ -81,6 +97,12 @@ struct srcu_notifier_head { init_rwsem(&(name)->rwsem); \ (name)->head = NULL; \ } while (0) +#define TUNABLE_ATOMIC_INIT_NOTIFIER(val1, val2) do { \ + spin_lock_init(&(val1)->lock); \ + (val1)->head = NULL; \ + (val1)->name = val2; \ + (val1)->dir = NULL; \ + } while (0) #define RAW_INIT_NOTIFIER_HEAD(name) do { \ (name)->head = NULL; \ } while (0) @@ -96,6 +118,11 @@ extern void srcu_init_notifier_head(stru #define BLOCKING_NOTIFIER_INIT(name) { \ .rwsem = __RWSEM_INITIALIZER((name).rwsem), \ .head = NULL } +#define TUNABLE_ATOMIC_NOTIFIER_INIT(val1, val2) { \ + .lock =__SPIN_LOCK_UNLOCKED(val1.lock), \ + .head = NULL, \ + .name = val2, \ + .dir = NULL } #define RAW_NOTIFIER_INIT(name) { \ .head = NULL } /* srcu_notifier_heads cannot be initialized statically */ @@ -106,6 +133,9 @@ extern void srcu_init_notifier_head(stru #define BLOCKING_NOTIFIER_HEAD(name) \ struct blocking_notifier_head name = \ BLOCKING_NOTIFIER_INIT(name) +#define TUNABLE_ATOMIC_NOTIFIER_HEAD(name, val) \ + struct tunable_atomic_notifier_head name = \ + TUNABLE_ATOMIC_NOTIFIER_INIT(name, val) #define RAW_NOTIFIER_HEAD(name) \ struct raw_notifier_head name = \ RAW_NOTIFIER_INIT(name) @@ -116,6 +146,10 @@ extern int atomic_notifier_chain_registe struct notifier_block *nb); extern int blocking_notifier_chain_register(struct blocking_notifier_head *nh, struct notifier_block *nb); +extern int tunable_atomic_notifier_chain_register( + struct tunable_atomic_notifier_head *nh, + struct tunable_atomic_notifier_block *nb, + char *name, char *desc); extern int raw_notifier_chain_register(struct raw_notifier_head *nh, struct notifier_block *nb); extern int srcu_notifier_chain_register(struct srcu_notifier_head *nh, @@ -125,6 +159,9 @@ extern int atomic_notifier_chain_unregis struct notifier_block *nb); extern int blocking_notifier_chain_unregister(struct blocking_notifier_head *nh, struct notifier_block *nb); +extern int tunable_atomic_notifier_chain_unregister( + struct tunable_atomic_notifier_head *nh, + struct tunable_atomic_notifier_block *nb); extern int raw_notifier_chain_unregister(struct raw_notifier_head *nh, struct notifier_block *nb); extern int srcu_notifier_chain_unregister(struct srcu_notifier_head *nh, @@ -138,6 +175,13 @@ extern int blocking_notifier_call_chain( unsigned long val, void *v); extern int __blocking_notifier_call_chain(struct blocking_notifier_head *nh, unsigned long val, void *v, int nr_to_call, int *nr_calls); +extern int tunable_atomic_notifier_call_chain( + struct tunable_atomic_notifier_head *nh, + unsigned long val, void *v); +extern int __tunable_atomic_notifier_call_chain( + struct tunable_atomic_notifier_head *nh, + unsigned long val, void *v, + int nr_to_call, int *nr_calls); extern int raw_notifier_call_chain(struct raw_notifier_head *nh, unsigned long val, void *v); extern int __raw_notifier_call_chain(struct raw_notifier_head *nh, diff -uprN linux-2.6.23.orig/kernel/sys.c linux-2.6.23/kernel/sys.c --- linux-2.6.23.orig/kernel/sys.c 2007-10-10 05:31:38.000000000 +0900 +++ linux-2.6.23/kernel/sys.c 2007-10-18 10:08:52.728000000 +0900 @@ -38,6 +38,7 @@ #include <linux/syscalls.h> #include <linux/kprobes.h> #include <linux/user_namespace.h> +#include <linux/debugfs.h> #include <asm/uaccess.h> #include <asm/io.h> @@ -393,6 +394,243 @@ int blocking_notifier_call_chain(struct EXPORT_SYMBOL_GPL(blocking_notifier_call_chain); /* + * Tunable atomic notifier chain routines. Registration and unregistration + * use a spinlock, and call_chain is synchronized by RCU (no locks). + * User can change the list order to use /sys/kernel/debug/list-name/. + */ + +static ssize_t priority_read(struct file *file, + char __user *user_buf, size_t count, loff_t *ppos) +{ + struct tunable_atomic_notifier_block *n = + file->f_dentry->d_inode->i_private; + int priority = n->nb->priority; + char buf[64], *s; + + s = buf; + s += sprintf(s, "%d\n", priority); + + return simple_read_from_buffer((void __user *)user_buf, count, + ppos, buf, s - buf); +} + +static ssize_t priority_write(struct file *file, + const char __user *user_buf, size_t count, loff_t *ppos) +{ + struct tunable_atomic_notifier_block *n = + file->f_dentry->d_inode->i_private; + struct tunable_atomic_notifier_head *nh = n->head; + char *buf, *end; + int ret = -ENOMEM, priority; + unsigned long tmp, flags; + + buf = kmalloc(count + 1, GFP_KERNEL); + if (!buf) + goto out; + + buf[count] = 0; + ret = -EFAULT; + if (copy_from_user(buf, user_buf, count)) + goto out_free; + + ret = -EINVAL; + tmp = simple_strtoul(buf, &end, 10); + if ((end == buf) || (tmp > INT_MAX)) + goto out_free; + + priority = (int)tmp; + n->nb->priority = priority; + + spin_lock_irqsave(&nh->lock, flags); + ret = notifier_chain_unregister(&nh->head, n->nb); + if (ret) + goto out_unlock; + ret = notifier_chain_register(&nh->head, n->nb); + if (!ret) + ret = count; + +out_unlock: + spin_unlock_irqrestore(&nh->lock, flags); +out_free: + kfree(buf); +out: + return ret; + +} + +static const struct file_operations pri_fops = { + .read = priority_read, + .write = priority_write, +}; + +static ssize_t description_read(struct file *file, + char __user *user_buf, size_t count, loff_t *ppos) +{ + char *desc = file->f_dentry->d_inode->i_private; + int avail = strlen(desc); + + return simple_read_from_buffer(user_buf, count, ppos, desc, avail); +} + +static const struct file_operations desc_fops = { + .read = description_read, +}; + +/** + * tunable_atomic_notifier_chain_register + * - Add notifier to an tunable notifier chain + * @nh: Pointer to head of the tunable notifier chain + * @n: New entry in notifier chain + * @name: Pointer to the name of the new notifier entry + * @desc: Pointer to the description of new entry + * + * Adds a notifier to an tunable notifier chain and makes control dir. + * + * Returns zero on success or %-ENODEV on failure. + */ + +int tunable_atomic_notifier_chain_register( + struct tunable_atomic_notifier_head *nh, + struct tunable_atomic_notifier_block *n, char *name, char *desc) +{ + unsigned long flags; + int ret = -EINVAL; + struct dentry *nh_dir, *nb_dir, *pri_dentry, *desc_dentry = NULL; + + if (!name) + goto nb_fail; + + ret = -ENOMEM; + if (!nh->dir) { + nh_dir = debugfs_create_dir(nh->name, NULL); + if (!nh_dir) + return ret; + nh->dir = nh_dir; + } else + nh_dir = nh->dir; + + nb_dir = debugfs_create_dir(name, nh_dir); + if (!nb_dir) + goto nb_fail; + n->dir = nb_dir; + + pri_dentry = debugfs_create_file("priority",0600, nb_dir, n, &pri_fops); + if (!pri_dentry) + goto pri_fail; + n->pri_dentry = pri_dentry; + + if (desc) { + desc_dentry = debugfs_create_file("description", 0400, nb_dir, + desc, &desc_fops); + if (!desc_dentry) + goto desc_fail; + n->desc_dentry = desc_dentry; + } + + spin_lock_irqsave(&nh->lock, flags); + ret = notifier_chain_register(&nh->head, n->nb); + spin_unlock_irqrestore(&nh->lock, flags); + + if (ret) + goto reg_fail; + + n->head = nh; + + return ret; + +reg_fail: + debugfs_remove(desc_dentry); +desc_fail: + debugfs_remove(pri_dentry); +pri_fail: + debugfs_remove(nb_dir); +nb_fail: + return ret; +} + +EXPORT_SYMBOL_GPL(tunable_atomic_notifier_chain_register); + +/** + * tunable_atomic_notifier_chain_unregister + * - Remove notifier from a tunable notifier chain + * @nh: Pointer to head of the tunable notifier chain + * @n: Entry to remove from notifier chain + * + * Removes a notifier from a tunable notifier chain. + * + * Retunrns zero on success or %-ENOENT on failure. + */ + +int tunable_atomic_notifier_chain_unregister( + struct tunable_atomic_notifier_head *nh, + struct tunable_atomic_notifier_block *n) +{ + unsigned long flags; + int ret; + + spin_lock_irqsave(&nh->lock, flags); + ret = notifier_chain_unregister(&nh->head, n->nb); + spin_unlock_irqrestore(&nh->lock, flags); + synchronize_rcu(); + + if (ret) + return ret; + + debugfs_remove(n->desc_dentry); + debugfs_remove(n->pri_dentry); + debugfs_remove(n->dir); + + return 0; +} + +EXPORT_SYMBOL_GPL(tunable_atomic_notifier_chain_unregister); + +/** + * __tunable_atomic_notifier_call_chain + * - Call functions in a tunable notifier chain + * @nh: Pointer to head of the tunable notifier chain + * @val: Value passed unmodified to notifier function + * @v: Pointer passed unmodified to notifier function + * @nt_to_call: See the comment for notifier_call_chain + * @nr_calls: See the comment for notifier_call_chain + * + * Calls each function in a notifier chain in turn. The functions + * run in an atomic context, so they must not block. + * This routine uses RCU to synchronize with changes to the chain. + * + * If the return value of the notifier can be and'ed + * with %NOTIFY_STOP_MASK then tunable_atomic_notifier_call_chain() + * will return immediately, with the return value of + * the notifier function which halted execution. + * Otherwise the return value is the return value + * of the last notifier function called. + */ + +int __kprobes __tunable_atomic_notifier_call_chain( + struct tunable_atomic_notifier_head *nh, + unsigned long val, void *v, + int nr_to_call, int *nr_calls) +{ + int ret; + + rcu_read_lock(); + ret = notifier_call_chain(&nh->head, val, v, nr_to_call, nr_calls); + rcu_read_unlock(); + return ret; +} + +EXPORT_SYMBOL_GPL(__tunable_atomic_notifier_call_chain); + +int __kprobes tunable_atomic_notifier_call_chain( + struct tunable_atomic_notifier_head *nh, + unsigned long val, void *v) +{ + return __tunable_atomic_notifier_call_chain(nh, val, v, -1, NULL); +} + +EXPORT_SYMBOL_GPL(tunable_atomic_notifier_call_chain); + +/* * Raw notifier chain routines. There is no protection; * the caller must provide it. Use at your own risk! */ _______________________________________________ kexec mailing list kexec@lists.infradead.org http://lists.infradead.org/mailman/listinfo/kexec ^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 1/2] add tunable_notifier function ,take2 @ 2007-10-18 6:45 ` Takenori Nagano 0 siblings, 0 replies; 14+ messages in thread From: Takenori Nagano @ 2007-10-18 6:45 UTC (permalink / raw) To: linux-kernel Cc: vgoyal, Eric W. Biederman, k-miyoshi, kexec, Bernhard Walle, Keith Owens, Andrew Morton, kdb This patch adds new notifier function tunable_notifier_chain. Its base is atomic_notifier_chain. Thanks, --- Signed-off-by: Takenori Nagano <t-nagano@ah.jp.nec.com> --- diff -uprN linux-2.6.23.orig/include/linux/notifier.h linux-2.6.23/include/linux/notifier.h --- linux-2.6.23.orig/include/linux/notifier.h 2007-10-10 05:31:38.000000000 +0900 +++ linux-2.6.23/include/linux/notifier.h 2007-10-18 09:59:13.732000000 +0900 @@ -13,6 +13,7 @@ #include <linux/mutex.h> #include <linux/rwsem.h> #include <linux/srcu.h> +#include <linux/kobject.h> /* * Notifier chains are of four types: @@ -53,6 +54,14 @@ struct notifier_block { int priority; }; +struct tunable_atomic_notifier_block { + struct notifier_block *nb; + struct tunable_atomic_notifier_head *head; + struct dentry *dir; + struct dentry *pri_dentry; + struct dentry *desc_dentry; +}; + struct atomic_notifier_head { spinlock_t lock; struct notifier_block *head; @@ -63,6 +72,13 @@ struct blocking_notifier_head { struct notifier_block *head; }; +struct tunable_atomic_notifier_head { + spinlock_t lock; + struct notifier_block *head; + char *name; + struct dentry *dir; +}; + struct raw_notifier_head { struct notifier_block *head; }; @@ -81,6 +97,12 @@ struct srcu_notifier_head { init_rwsem(&(name)->rwsem); \ (name)->head = NULL; \ } while (0) +#define TUNABLE_ATOMIC_INIT_NOTIFIER(val1, val2) do { \ + spin_lock_init(&(val1)->lock); \ + (val1)->head = NULL; \ + (val1)->name = val2; \ + (val1)->dir = NULL; \ + } while (0) #define RAW_INIT_NOTIFIER_HEAD(name) do { \ (name)->head = NULL; \ } while (0) @@ -96,6 +118,11 @@ extern void srcu_init_notifier_head(stru #define BLOCKING_NOTIFIER_INIT(name) { \ .rwsem = __RWSEM_INITIALIZER((name).rwsem), \ .head = NULL } +#define TUNABLE_ATOMIC_NOTIFIER_INIT(val1, val2) { \ + .lock =__SPIN_LOCK_UNLOCKED(val1.lock), \ + .head = NULL, \ + .name = val2, \ + .dir = NULL } #define RAW_NOTIFIER_INIT(name) { \ .head = NULL } /* srcu_notifier_heads cannot be initialized statically */ @@ -106,6 +133,9 @@ extern void srcu_init_notifier_head(stru #define BLOCKING_NOTIFIER_HEAD(name) \ struct blocking_notifier_head name = \ BLOCKING_NOTIFIER_INIT(name) +#define TUNABLE_ATOMIC_NOTIFIER_HEAD(name, val) \ + struct tunable_atomic_notifier_head name = \ + TUNABLE_ATOMIC_NOTIFIER_INIT(name, val) #define RAW_NOTIFIER_HEAD(name) \ struct raw_notifier_head name = \ RAW_NOTIFIER_INIT(name) @@ -116,6 +146,10 @@ extern int atomic_notifier_chain_registe struct notifier_block *nb); extern int blocking_notifier_chain_register(struct blocking_notifier_head *nh, struct notifier_block *nb); +extern int tunable_atomic_notifier_chain_register( + struct tunable_atomic_notifier_head *nh, + struct tunable_atomic_notifier_block *nb, + char *name, char *desc); extern int raw_notifier_chain_register(struct raw_notifier_head *nh, struct notifier_block *nb); extern int srcu_notifier_chain_register(struct srcu_notifier_head *nh, @@ -125,6 +159,9 @@ extern int atomic_notifier_chain_unregis struct notifier_block *nb); extern int blocking_notifier_chain_unregister(struct blocking_notifier_head *nh, struct notifier_block *nb); +extern int tunable_atomic_notifier_chain_unregister( + struct tunable_atomic_notifier_head *nh, + struct tunable_atomic_notifier_block *nb); extern int raw_notifier_chain_unregister(struct raw_notifier_head *nh, struct notifier_block *nb); extern int srcu_notifier_chain_unregister(struct srcu_notifier_head *nh, @@ -138,6 +175,13 @@ extern int blocking_notifier_call_chain( unsigned long val, void *v); extern int __blocking_notifier_call_chain(struct blocking_notifier_head *nh, unsigned long val, void *v, int nr_to_call, int *nr_calls); +extern int tunable_atomic_notifier_call_chain( + struct tunable_atomic_notifier_head *nh, + unsigned long val, void *v); +extern int __tunable_atomic_notifier_call_chain( + struct tunable_atomic_notifier_head *nh, + unsigned long val, void *v, + int nr_to_call, int *nr_calls); extern int raw_notifier_call_chain(struct raw_notifier_head *nh, unsigned long val, void *v); extern int __raw_notifier_call_chain(struct raw_notifier_head *nh, diff -uprN linux-2.6.23.orig/kernel/sys.c linux-2.6.23/kernel/sys.c --- linux-2.6.23.orig/kernel/sys.c 2007-10-10 05:31:38.000000000 +0900 +++ linux-2.6.23/kernel/sys.c 2007-10-18 10:08:52.728000000 +0900 @@ -38,6 +38,7 @@ #include <linux/syscalls.h> #include <linux/kprobes.h> #include <linux/user_namespace.h> +#include <linux/debugfs.h> #include <asm/uaccess.h> #include <asm/io.h> @@ -393,6 +394,243 @@ int blocking_notifier_call_chain(struct EXPORT_SYMBOL_GPL(blocking_notifier_call_chain); /* + * Tunable atomic notifier chain routines. Registration and unregistration + * use a spinlock, and call_chain is synchronized by RCU (no locks). + * User can change the list order to use /sys/kernel/debug/list-name/. + */ + +static ssize_t priority_read(struct file *file, + char __user *user_buf, size_t count, loff_t *ppos) +{ + struct tunable_atomic_notifier_block *n = + file->f_dentry->d_inode->i_private; + int priority = n->nb->priority; + char buf[64], *s; + + s = buf; + s += sprintf(s, "%d\n", priority); + + return simple_read_from_buffer((void __user *)user_buf, count, + ppos, buf, s - buf); +} + +static ssize_t priority_write(struct file *file, + const char __user *user_buf, size_t count, loff_t *ppos) +{ + struct tunable_atomic_notifier_block *n = + file->f_dentry->d_inode->i_private; + struct tunable_atomic_notifier_head *nh = n->head; + char *buf, *end; + int ret = -ENOMEM, priority; + unsigned long tmp, flags; + + buf = kmalloc(count + 1, GFP_KERNEL); + if (!buf) + goto out; + + buf[count] = 0; + ret = -EFAULT; + if (copy_from_user(buf, user_buf, count)) + goto out_free; + + ret = -EINVAL; + tmp = simple_strtoul(buf, &end, 10); + if ((end == buf) || (tmp > INT_MAX)) + goto out_free; + + priority = (int)tmp; + n->nb->priority = priority; + + spin_lock_irqsave(&nh->lock, flags); + ret = notifier_chain_unregister(&nh->head, n->nb); + if (ret) + goto out_unlock; + ret = notifier_chain_register(&nh->head, n->nb); + if (!ret) + ret = count; + +out_unlock: + spin_unlock_irqrestore(&nh->lock, flags); +out_free: + kfree(buf); +out: + return ret; + +} + +static const struct file_operations pri_fops = { + .read = priority_read, + .write = priority_write, +}; + +static ssize_t description_read(struct file *file, + char __user *user_buf, size_t count, loff_t *ppos) +{ + char *desc = file->f_dentry->d_inode->i_private; + int avail = strlen(desc); + + return simple_read_from_buffer(user_buf, count, ppos, desc, avail); +} + +static const struct file_operations desc_fops = { + .read = description_read, +}; + +/** + * tunable_atomic_notifier_chain_register + * - Add notifier to an tunable notifier chain + * @nh: Pointer to head of the tunable notifier chain + * @n: New entry in notifier chain + * @name: Pointer to the name of the new notifier entry + * @desc: Pointer to the description of new entry + * + * Adds a notifier to an tunable notifier chain and makes control dir. + * + * Returns zero on success or %-ENODEV on failure. + */ + +int tunable_atomic_notifier_chain_register( + struct tunable_atomic_notifier_head *nh, + struct tunable_atomic_notifier_block *n, char *name, char *desc) +{ + unsigned long flags; + int ret = -EINVAL; + struct dentry *nh_dir, *nb_dir, *pri_dentry, *desc_dentry = NULL; + + if (!name) + goto nb_fail; + + ret = -ENOMEM; + if (!nh->dir) { + nh_dir = debugfs_create_dir(nh->name, NULL); + if (!nh_dir) + return ret; + nh->dir = nh_dir; + } else + nh_dir = nh->dir; + + nb_dir = debugfs_create_dir(name, nh_dir); + if (!nb_dir) + goto nb_fail; + n->dir = nb_dir; + + pri_dentry = debugfs_create_file("priority",0600, nb_dir, n, &pri_fops); + if (!pri_dentry) + goto pri_fail; + n->pri_dentry = pri_dentry; + + if (desc) { + desc_dentry = debugfs_create_file("description", 0400, nb_dir, + desc, &desc_fops); + if (!desc_dentry) + goto desc_fail; + n->desc_dentry = desc_dentry; + } + + spin_lock_irqsave(&nh->lock, flags); + ret = notifier_chain_register(&nh->head, n->nb); + spin_unlock_irqrestore(&nh->lock, flags); + + if (ret) + goto reg_fail; + + n->head = nh; + + return ret; + +reg_fail: + debugfs_remove(desc_dentry); +desc_fail: + debugfs_remove(pri_dentry); +pri_fail: + debugfs_remove(nb_dir); +nb_fail: + return ret; +} + +EXPORT_SYMBOL_GPL(tunable_atomic_notifier_chain_register); + +/** + * tunable_atomic_notifier_chain_unregister + * - Remove notifier from a tunable notifier chain + * @nh: Pointer to head of the tunable notifier chain + * @n: Entry to remove from notifier chain + * + * Removes a notifier from a tunable notifier chain. + * + * Retunrns zero on success or %-ENOENT on failure. + */ + +int tunable_atomic_notifier_chain_unregister( + struct tunable_atomic_notifier_head *nh, + struct tunable_atomic_notifier_block *n) +{ + unsigned long flags; + int ret; + + spin_lock_irqsave(&nh->lock, flags); + ret = notifier_chain_unregister(&nh->head, n->nb); + spin_unlock_irqrestore(&nh->lock, flags); + synchronize_rcu(); + + if (ret) + return ret; + + debugfs_remove(n->desc_dentry); + debugfs_remove(n->pri_dentry); + debugfs_remove(n->dir); + + return 0; +} + +EXPORT_SYMBOL_GPL(tunable_atomic_notifier_chain_unregister); + +/** + * __tunable_atomic_notifier_call_chain + * - Call functions in a tunable notifier chain + * @nh: Pointer to head of the tunable notifier chain + * @val: Value passed unmodified to notifier function + * @v: Pointer passed unmodified to notifier function + * @nt_to_call: See the comment for notifier_call_chain + * @nr_calls: See the comment for notifier_call_chain + * + * Calls each function in a notifier chain in turn. The functions + * run in an atomic context, so they must not block. + * This routine uses RCU to synchronize with changes to the chain. + * + * If the return value of the notifier can be and'ed + * with %NOTIFY_STOP_MASK then tunable_atomic_notifier_call_chain() + * will return immediately, with the return value of + * the notifier function which halted execution. + * Otherwise the return value is the return value + * of the last notifier function called. + */ + +int __kprobes __tunable_atomic_notifier_call_chain( + struct tunable_atomic_notifier_head *nh, + unsigned long val, void *v, + int nr_to_call, int *nr_calls) +{ + int ret; + + rcu_read_lock(); + ret = notifier_call_chain(&nh->head, val, v, nr_to_call, nr_calls); + rcu_read_unlock(); + return ret; +} + +EXPORT_SYMBOL_GPL(__tunable_atomic_notifier_call_chain); + +int __kprobes tunable_atomic_notifier_call_chain( + struct tunable_atomic_notifier_head *nh, + unsigned long val, void *v) +{ + return __tunable_atomic_notifier_call_chain(nh, val, v, -1, NULL); +} + +EXPORT_SYMBOL_GPL(tunable_atomic_notifier_call_chain); + +/* * Raw notifier chain routines. There is no protection; * the caller must provide it. Use at your own risk! */ ^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 1/2] add tunable_notifier function ,take2 [not found] <4716FFDB.7090502@ah.jp.nec.com> @ 2007-10-18 8:53 ` Takenori Nagano 2007-10-18 8:53 ` Takenori Nagano 1 sibling, 0 replies; 14+ messages in thread From: Takenori Nagano @ 2007-10-18 8:53 UTC (permalink / raw) To: linux-kernel Cc: k-miyoshi, Bernhard Walle, kdb, kexec, vgoyal, Eric W. Biederman, Keith Owens, Andrew Morton This patch adds new notifier function tunable_notifier_chain. Its base is atomic_notifier_chain. Thanks, --- Signed-off-by: Takenori Nagano <t-nagano@ah.jp.nec.com> --- diff -uprN linux-2.6.23.orig/include/linux/notifier.h linux-2.6.23/include/linux/notifier.h --- linux-2.6.23.orig/include/linux/notifier.h 2007-10-10 05:31:38.000000000 +0900 +++ linux-2.6.23/include/linux/notifier.h 2007-10-18 09:59:13.732000000 +0900 @@ -13,6 +13,7 @@ #include <linux/mutex.h> #include <linux/rwsem.h> #include <linux/srcu.h> +#include <linux/kobject.h> /* * Notifier chains are of four types: @@ -53,6 +54,14 @@ struct notifier_block { int priority; }; +struct tunable_atomic_notifier_block { + struct notifier_block *nb; + struct tunable_atomic_notifier_head *head; + struct dentry *dir; + struct dentry *pri_dentry; + struct dentry *desc_dentry; +}; + struct atomic_notifier_head { spinlock_t lock; struct notifier_block *head; @@ -63,6 +72,13 @@ struct blocking_notifier_head { struct notifier_block *head; }; +struct tunable_atomic_notifier_head { + spinlock_t lock; + struct notifier_block *head; + char *name; + struct dentry *dir; +}; + struct raw_notifier_head { struct notifier_block *head; }; @@ -81,6 +97,12 @@ struct srcu_notifier_head { init_rwsem(&(name)->rwsem); \ (name)->head = NULL; \ } while (0) +#define TUNABLE_ATOMIC_INIT_NOTIFIER(val1, val2) do { \ + spin_lock_init(&(val1)->lock); \ + (val1)->head = NULL; \ + (val1)->name = val2; \ + (val1)->dir = NULL; \ + } while (0) #define RAW_INIT_NOTIFIER_HEAD(name) do { \ (name)->head = NULL; \ } while (0) @@ -96,6 +118,11 @@ extern void srcu_init_notifier_head(stru #define BLOCKING_NOTIFIER_INIT(name) { \ .rwsem = __RWSEM_INITIALIZER((name).rwsem), \ .head = NULL } +#define TUNABLE_ATOMIC_NOTIFIER_INIT(val1, val2) { \ + .lock =__SPIN_LOCK_UNLOCKED(val1.lock), \ + .head = NULL, \ + .name = val2, \ + .dir = NULL } #define RAW_NOTIFIER_INIT(name) { \ .head = NULL } /* srcu_notifier_heads cannot be initialized statically */ @@ -106,6 +133,9 @@ extern void srcu_init_notifier_head(stru #define BLOCKING_NOTIFIER_HEAD(name) \ struct blocking_notifier_head name = \ BLOCKING_NOTIFIER_INIT(name) +#define TUNABLE_ATOMIC_NOTIFIER_HEAD(name, val) \ + struct tunable_atomic_notifier_head name = \ + TUNABLE_ATOMIC_NOTIFIER_INIT(name, val) #define RAW_NOTIFIER_HEAD(name) \ struct raw_notifier_head name = \ RAW_NOTIFIER_INIT(name) @@ -116,6 +146,10 @@ extern int atomic_notifier_chain_registe struct notifier_block *nb); extern int blocking_notifier_chain_register(struct blocking_notifier_head *nh, struct notifier_block *nb); +extern int tunable_atomic_notifier_chain_register( + struct tunable_atomic_notifier_head *nh, + struct tunable_atomic_notifier_block *nb, + char *name, char *desc); extern int raw_notifier_chain_register(struct raw_notifier_head *nh, struct notifier_block *nb); extern int srcu_notifier_chain_register(struct srcu_notifier_head *nh, @@ -125,6 +159,9 @@ extern int atomic_notifier_chain_unregis struct notifier_block *nb); extern int blocking_notifier_chain_unregister(struct blocking_notifier_head *nh, struct notifier_block *nb); +extern int tunable_atomic_notifier_chain_unregister( + struct tunable_atomic_notifier_head *nh, + struct tunable_atomic_notifier_block *nb); extern int raw_notifier_chain_unregister(struct raw_notifier_head *nh, struct notifier_block *nb); extern int srcu_notifier_chain_unregister(struct srcu_notifier_head *nh, @@ -138,6 +175,13 @@ extern int blocking_notifier_call_chain( unsigned long val, void *v); extern int __blocking_notifier_call_chain(struct blocking_notifier_head *nh, unsigned long val, void *v, int nr_to_call, int *nr_calls); +extern int tunable_atomic_notifier_call_chain( + struct tunable_atomic_notifier_head *nh, + unsigned long val, void *v); +extern int __tunable_atomic_notifier_call_chain( + struct tunable_atomic_notifier_head *nh, + unsigned long val, void *v, + int nr_to_call, int *nr_calls); extern int raw_notifier_call_chain(struct raw_notifier_head *nh, unsigned long val, void *v); extern int __raw_notifier_call_chain(struct raw_notifier_head *nh, diff -uprN linux-2.6.23.orig/kernel/sys.c linux-2.6.23/kernel/sys.c --- linux-2.6.23.orig/kernel/sys.c 2007-10-10 05:31:38.000000000 +0900 +++ linux-2.6.23/kernel/sys.c 2007-10-18 10:08:52.728000000 +0900 @@ -38,6 +38,7 @@ #include <linux/syscalls.h> #include <linux/kprobes.h> #include <linux/user_namespace.h> +#include <linux/debugfs.h> #include <asm/uaccess.h> #include <asm/io.h> @@ -393,6 +394,243 @@ int blocking_notifier_call_chain(struct EXPORT_SYMBOL_GPL(blocking_notifier_call_chain); /* + * Tunable atomic notifier chain routines. Registration and unregistration + * use a spinlock, and call_chain is synchronized by RCU (no locks). + * User can change the list order to use /sys/kernel/debug/list-name/. + */ + +static ssize_t priority_read(struct file *file, + char __user *user_buf, size_t count, loff_t *ppos) +{ + struct tunable_atomic_notifier_block *n = + file->f_dentry->d_inode->i_private; + int priority = n->nb->priority; + char buf[64], *s; + + s = buf; + s += sprintf(s, "%d\n", priority); + + return simple_read_from_buffer((void __user *)user_buf, count, + ppos, buf, s - buf); +} + +static ssize_t priority_write(struct file *file, + const char __user *user_buf, size_t count, loff_t *ppos) +{ + struct tunable_atomic_notifier_block *n = + file->f_dentry->d_inode->i_private; + struct tunable_atomic_notifier_head *nh = n->head; + char *buf, *end; + int ret = -ENOMEM, priority; + unsigned long tmp, flags; + + buf = kmalloc(count + 1, GFP_KERNEL); + if (!buf) + goto out; + + buf[count] = 0; + ret = -EFAULT; + if (copy_from_user(buf, user_buf, count)) + goto out_free; + + ret = -EINVAL; + tmp = simple_strtoul(buf, &end, 10); + if ((end == buf) || (tmp > INT_MAX)) + goto out_free; + + priority = (int)tmp; + n->nb->priority = priority; + + spin_lock_irqsave(&nh->lock, flags); + ret = notifier_chain_unregister(&nh->head, n->nb); + if (ret) + goto out_unlock; + ret = notifier_chain_register(&nh->head, n->nb); + if (!ret) + ret = count; + +out_unlock: + spin_unlock_irqrestore(&nh->lock, flags); +out_free: + kfree(buf); +out: + return ret; + +} + +static const struct file_operations pri_fops = { + .read = priority_read, + .write = priority_write, +}; + +static ssize_t description_read(struct file *file, + char __user *user_buf, size_t count, loff_t *ppos) +{ + char *desc = file->f_dentry->d_inode->i_private; + int avail = strlen(desc); + + return simple_read_from_buffer(user_buf, count, ppos, desc, avail); +} + +static const struct file_operations desc_fops = { + .read = description_read, +}; + +/** + * tunable_atomic_notifier_chain_register + * - Add notifier to an tunable notifier chain + * @nh: Pointer to head of the tunable notifier chain + * @n: New entry in notifier chain + * @name: Pointer to the name of the new notifier entry + * @desc: Pointer to the description of new entry + * + * Adds a notifier to an tunable notifier chain and makes control dir. + * + * Returns zero on success or %-ENODEV on failure. + */ + +int tunable_atomic_notifier_chain_register( + struct tunable_atomic_notifier_head *nh, + struct tunable_atomic_notifier_block *n, char *name, char *desc) +{ + unsigned long flags; + int ret = -EINVAL; + struct dentry *nh_dir, *nb_dir, *pri_dentry, *desc_dentry = NULL; + + if (!name) + goto nb_fail; + + ret = -ENOMEM; + if (!nh->dir) { + nh_dir = debugfs_create_dir(nh->name, NULL); + if (!nh_dir) + return ret; + nh->dir = nh_dir; + } else + nh_dir = nh->dir; + + nb_dir = debugfs_create_dir(name, nh_dir); + if (!nb_dir) + goto nb_fail; + n->dir = nb_dir; + + pri_dentry = debugfs_create_file("priority",0600, nb_dir, n, &pri_fops); + if (!pri_dentry) + goto pri_fail; + n->pri_dentry = pri_dentry; + + if (desc) { + desc_dentry = debugfs_create_file("description", 0400, nb_dir, + desc, &desc_fops); + if (!desc_dentry) + goto desc_fail; + n->desc_dentry = desc_dentry; + } + + spin_lock_irqsave(&nh->lock, flags); + ret = notifier_chain_register(&nh->head, n->nb); + spin_unlock_irqrestore(&nh->lock, flags); + + if (ret) + goto reg_fail; + + n->head = nh; + + return ret; + +reg_fail: + debugfs_remove(desc_dentry); +desc_fail: + debugfs_remove(pri_dentry); +pri_fail: + debugfs_remove(nb_dir); +nb_fail: + return ret; +} + +EXPORT_SYMBOL_GPL(tunable_atomic_notifier_chain_register); + +/** + * tunable_atomic_notifier_chain_unregister + * - Remove notifier from a tunable notifier chain + * @nh: Pointer to head of the tunable notifier chain + * @n: Entry to remove from notifier chain + * + * Removes a notifier from a tunable notifier chain. + * + * Retunrns zero on success or %-ENOENT on failure. + */ + +int tunable_atomic_notifier_chain_unregister( + struct tunable_atomic_notifier_head *nh, + struct tunable_atomic_notifier_block *n) +{ + unsigned long flags; + int ret; + + spin_lock_irqsave(&nh->lock, flags); + ret = notifier_chain_unregister(&nh->head, n->nb); + spin_unlock_irqrestore(&nh->lock, flags); + synchronize_rcu(); + + if (ret) + return ret; + + debugfs_remove(n->desc_dentry); + debugfs_remove(n->pri_dentry); + debugfs_remove(n->dir); + + return 0; +} + +EXPORT_SYMBOL_GPL(tunable_atomic_notifier_chain_unregister); + +/** + * __tunable_atomic_notifier_call_chain + * - Call functions in a tunable notifier chain + * @nh: Pointer to head of the tunable notifier chain + * @val: Value passed unmodified to notifier function + * @v: Pointer passed unmodified to notifier function + * @nt_to_call: See the comment for notifier_call_chain + * @nr_calls: See the comment for notifier_call_chain + * + * Calls each function in a notifier chain in turn. The functions + * run in an atomic context, so they must not block. + * This routine uses RCU to synchronize with changes to the chain. + * + * If the return value of the notifier can be and'ed + * with %NOTIFY_STOP_MASK then tunable_atomic_notifier_call_chain() + * will return immediately, with the return value of + * the notifier function which halted execution. + * Otherwise the return value is the return value + * of the last notifier function called. + */ + +int __kprobes __tunable_atomic_notifier_call_chain( + struct tunable_atomic_notifier_head *nh, + unsigned long val, void *v, + int nr_to_call, int *nr_calls) +{ + int ret; + + rcu_read_lock(); + ret = notifier_call_chain(&nh->head, val, v, nr_to_call, nr_calls); + rcu_read_unlock(); + return ret; +} + +EXPORT_SYMBOL_GPL(__tunable_atomic_notifier_call_chain); + +int __kprobes tunable_atomic_notifier_call_chain( + struct tunable_atomic_notifier_head *nh, + unsigned long val, void *v) +{ + return __tunable_atomic_notifier_call_chain(nh, val, v, -1, NULL); +} + +EXPORT_SYMBOL_GPL(tunable_atomic_notifier_call_chain); + +/* * Raw notifier chain routines. There is no protection; * the caller must provide it. Use at your own risk! */ _______________________________________________ kexec mailing list kexec@lists.infradead.org http://lists.infradead.org/mailman/listinfo/kexec ^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 1/2] add tunable_notifier function ,take2 @ 2007-10-18 8:53 ` Takenori Nagano 0 siblings, 0 replies; 14+ messages in thread From: Takenori Nagano @ 2007-10-18 8:53 UTC (permalink / raw) To: linux-kernel Cc: vgoyal, Eric W. Biederman, k-miyoshi, kexec, Bernhard Walle, Keith Owens, Andrew Morton, kdb This patch adds new notifier function tunable_notifier_chain. Its base is atomic_notifier_chain. Thanks, --- Signed-off-by: Takenori Nagano <t-nagano@ah.jp.nec.com> --- diff -uprN linux-2.6.23.orig/include/linux/notifier.h linux-2.6.23/include/linux/notifier.h --- linux-2.6.23.orig/include/linux/notifier.h 2007-10-10 05:31:38.000000000 +0900 +++ linux-2.6.23/include/linux/notifier.h 2007-10-18 09:59:13.732000000 +0900 @@ -13,6 +13,7 @@ #include <linux/mutex.h> #include <linux/rwsem.h> #include <linux/srcu.h> +#include <linux/kobject.h> /* * Notifier chains are of four types: @@ -53,6 +54,14 @@ struct notifier_block { int priority; }; +struct tunable_atomic_notifier_block { + struct notifier_block *nb; + struct tunable_atomic_notifier_head *head; + struct dentry *dir; + struct dentry *pri_dentry; + struct dentry *desc_dentry; +}; + struct atomic_notifier_head { spinlock_t lock; struct notifier_block *head; @@ -63,6 +72,13 @@ struct blocking_notifier_head { struct notifier_block *head; }; +struct tunable_atomic_notifier_head { + spinlock_t lock; + struct notifier_block *head; + char *name; + struct dentry *dir; +}; + struct raw_notifier_head { struct notifier_block *head; }; @@ -81,6 +97,12 @@ struct srcu_notifier_head { init_rwsem(&(name)->rwsem); \ (name)->head = NULL; \ } while (0) +#define TUNABLE_ATOMIC_INIT_NOTIFIER(val1, val2) do { \ + spin_lock_init(&(val1)->lock); \ + (val1)->head = NULL; \ + (val1)->name = val2; \ + (val1)->dir = NULL; \ + } while (0) #define RAW_INIT_NOTIFIER_HEAD(name) do { \ (name)->head = NULL; \ } while (0) @@ -96,6 +118,11 @@ extern void srcu_init_notifier_head(stru #define BLOCKING_NOTIFIER_INIT(name) { \ .rwsem = __RWSEM_INITIALIZER((name).rwsem), \ .head = NULL } +#define TUNABLE_ATOMIC_NOTIFIER_INIT(val1, val2) { \ + .lock =__SPIN_LOCK_UNLOCKED(val1.lock), \ + .head = NULL, \ + .name = val2, \ + .dir = NULL } #define RAW_NOTIFIER_INIT(name) { \ .head = NULL } /* srcu_notifier_heads cannot be initialized statically */ @@ -106,6 +133,9 @@ extern void srcu_init_notifier_head(stru #define BLOCKING_NOTIFIER_HEAD(name) \ struct blocking_notifier_head name = \ BLOCKING_NOTIFIER_INIT(name) +#define TUNABLE_ATOMIC_NOTIFIER_HEAD(name, val) \ + struct tunable_atomic_notifier_head name = \ + TUNABLE_ATOMIC_NOTIFIER_INIT(name, val) #define RAW_NOTIFIER_HEAD(name) \ struct raw_notifier_head name = \ RAW_NOTIFIER_INIT(name) @@ -116,6 +146,10 @@ extern int atomic_notifier_chain_registe struct notifier_block *nb); extern int blocking_notifier_chain_register(struct blocking_notifier_head *nh, struct notifier_block *nb); +extern int tunable_atomic_notifier_chain_register( + struct tunable_atomic_notifier_head *nh, + struct tunable_atomic_notifier_block *nb, + char *name, char *desc); extern int raw_notifier_chain_register(struct raw_notifier_head *nh, struct notifier_block *nb); extern int srcu_notifier_chain_register(struct srcu_notifier_head *nh, @@ -125,6 +159,9 @@ extern int atomic_notifier_chain_unregis struct notifier_block *nb); extern int blocking_notifier_chain_unregister(struct blocking_notifier_head *nh, struct notifier_block *nb); +extern int tunable_atomic_notifier_chain_unregister( + struct tunable_atomic_notifier_head *nh, + struct tunable_atomic_notifier_block *nb); extern int raw_notifier_chain_unregister(struct raw_notifier_head *nh, struct notifier_block *nb); extern int srcu_notifier_chain_unregister(struct srcu_notifier_head *nh, @@ -138,6 +175,13 @@ extern int blocking_notifier_call_chain( unsigned long val, void *v); extern int __blocking_notifier_call_chain(struct blocking_notifier_head *nh, unsigned long val, void *v, int nr_to_call, int *nr_calls); +extern int tunable_atomic_notifier_call_chain( + struct tunable_atomic_notifier_head *nh, + unsigned long val, void *v); +extern int __tunable_atomic_notifier_call_chain( + struct tunable_atomic_notifier_head *nh, + unsigned long val, void *v, + int nr_to_call, int *nr_calls); extern int raw_notifier_call_chain(struct raw_notifier_head *nh, unsigned long val, void *v); extern int __raw_notifier_call_chain(struct raw_notifier_head *nh, diff -uprN linux-2.6.23.orig/kernel/sys.c linux-2.6.23/kernel/sys.c --- linux-2.6.23.orig/kernel/sys.c 2007-10-10 05:31:38.000000000 +0900 +++ linux-2.6.23/kernel/sys.c 2007-10-18 10:08:52.728000000 +0900 @@ -38,6 +38,7 @@ #include <linux/syscalls.h> #include <linux/kprobes.h> #include <linux/user_namespace.h> +#include <linux/debugfs.h> #include <asm/uaccess.h> #include <asm/io.h> @@ -393,6 +394,243 @@ int blocking_notifier_call_chain(struct EXPORT_SYMBOL_GPL(blocking_notifier_call_chain); /* + * Tunable atomic notifier chain routines. Registration and unregistration + * use a spinlock, and call_chain is synchronized by RCU (no locks). + * User can change the list order to use /sys/kernel/debug/list-name/. + */ + +static ssize_t priority_read(struct file *file, + char __user *user_buf, size_t count, loff_t *ppos) +{ + struct tunable_atomic_notifier_block *n = + file->f_dentry->d_inode->i_private; + int priority = n->nb->priority; + char buf[64], *s; + + s = buf; + s += sprintf(s, "%d\n", priority); + + return simple_read_from_buffer((void __user *)user_buf, count, + ppos, buf, s - buf); +} + +static ssize_t priority_write(struct file *file, + const char __user *user_buf, size_t count, loff_t *ppos) +{ + struct tunable_atomic_notifier_block *n = + file->f_dentry->d_inode->i_private; + struct tunable_atomic_notifier_head *nh = n->head; + char *buf, *end; + int ret = -ENOMEM, priority; + unsigned long tmp, flags; + + buf = kmalloc(count + 1, GFP_KERNEL); + if (!buf) + goto out; + + buf[count] = 0; + ret = -EFAULT; + if (copy_from_user(buf, user_buf, count)) + goto out_free; + + ret = -EINVAL; + tmp = simple_strtoul(buf, &end, 10); + if ((end == buf) || (tmp > INT_MAX)) + goto out_free; + + priority = (int)tmp; + n->nb->priority = priority; + + spin_lock_irqsave(&nh->lock, flags); + ret = notifier_chain_unregister(&nh->head, n->nb); + if (ret) + goto out_unlock; + ret = notifier_chain_register(&nh->head, n->nb); + if (!ret) + ret = count; + +out_unlock: + spin_unlock_irqrestore(&nh->lock, flags); +out_free: + kfree(buf); +out: + return ret; + +} + +static const struct file_operations pri_fops = { + .read = priority_read, + .write = priority_write, +}; + +static ssize_t description_read(struct file *file, + char __user *user_buf, size_t count, loff_t *ppos) +{ + char *desc = file->f_dentry->d_inode->i_private; + int avail = strlen(desc); + + return simple_read_from_buffer(user_buf, count, ppos, desc, avail); +} + +static const struct file_operations desc_fops = { + .read = description_read, +}; + +/** + * tunable_atomic_notifier_chain_register + * - Add notifier to an tunable notifier chain + * @nh: Pointer to head of the tunable notifier chain + * @n: New entry in notifier chain + * @name: Pointer to the name of the new notifier entry + * @desc: Pointer to the description of new entry + * + * Adds a notifier to an tunable notifier chain and makes control dir. + * + * Returns zero on success or %-ENODEV on failure. + */ + +int tunable_atomic_notifier_chain_register( + struct tunable_atomic_notifier_head *nh, + struct tunable_atomic_notifier_block *n, char *name, char *desc) +{ + unsigned long flags; + int ret = -EINVAL; + struct dentry *nh_dir, *nb_dir, *pri_dentry, *desc_dentry = NULL; + + if (!name) + goto nb_fail; + + ret = -ENOMEM; + if (!nh->dir) { + nh_dir = debugfs_create_dir(nh->name, NULL); + if (!nh_dir) + return ret; + nh->dir = nh_dir; + } else + nh_dir = nh->dir; + + nb_dir = debugfs_create_dir(name, nh_dir); + if (!nb_dir) + goto nb_fail; + n->dir = nb_dir; + + pri_dentry = debugfs_create_file("priority",0600, nb_dir, n, &pri_fops); + if (!pri_dentry) + goto pri_fail; + n->pri_dentry = pri_dentry; + + if (desc) { + desc_dentry = debugfs_create_file("description", 0400, nb_dir, + desc, &desc_fops); + if (!desc_dentry) + goto desc_fail; + n->desc_dentry = desc_dentry; + } + + spin_lock_irqsave(&nh->lock, flags); + ret = notifier_chain_register(&nh->head, n->nb); + spin_unlock_irqrestore(&nh->lock, flags); + + if (ret) + goto reg_fail; + + n->head = nh; + + return ret; + +reg_fail: + debugfs_remove(desc_dentry); +desc_fail: + debugfs_remove(pri_dentry); +pri_fail: + debugfs_remove(nb_dir); +nb_fail: + return ret; +} + +EXPORT_SYMBOL_GPL(tunable_atomic_notifier_chain_register); + +/** + * tunable_atomic_notifier_chain_unregister + * - Remove notifier from a tunable notifier chain + * @nh: Pointer to head of the tunable notifier chain + * @n: Entry to remove from notifier chain + * + * Removes a notifier from a tunable notifier chain. + * + * Retunrns zero on success or %-ENOENT on failure. + */ + +int tunable_atomic_notifier_chain_unregister( + struct tunable_atomic_notifier_head *nh, + struct tunable_atomic_notifier_block *n) +{ + unsigned long flags; + int ret; + + spin_lock_irqsave(&nh->lock, flags); + ret = notifier_chain_unregister(&nh->head, n->nb); + spin_unlock_irqrestore(&nh->lock, flags); + synchronize_rcu(); + + if (ret) + return ret; + + debugfs_remove(n->desc_dentry); + debugfs_remove(n->pri_dentry); + debugfs_remove(n->dir); + + return 0; +} + +EXPORT_SYMBOL_GPL(tunable_atomic_notifier_chain_unregister); + +/** + * __tunable_atomic_notifier_call_chain + * - Call functions in a tunable notifier chain + * @nh: Pointer to head of the tunable notifier chain + * @val: Value passed unmodified to notifier function + * @v: Pointer passed unmodified to notifier function + * @nt_to_call: See the comment for notifier_call_chain + * @nr_calls: See the comment for notifier_call_chain + * + * Calls each function in a notifier chain in turn. The functions + * run in an atomic context, so they must not block. + * This routine uses RCU to synchronize with changes to the chain. + * + * If the return value of the notifier can be and'ed + * with %NOTIFY_STOP_MASK then tunable_atomic_notifier_call_chain() + * will return immediately, with the return value of + * the notifier function which halted execution. + * Otherwise the return value is the return value + * of the last notifier function called. + */ + +int __kprobes __tunable_atomic_notifier_call_chain( + struct tunable_atomic_notifier_head *nh, + unsigned long val, void *v, + int nr_to_call, int *nr_calls) +{ + int ret; + + rcu_read_lock(); + ret = notifier_call_chain(&nh->head, val, v, nr_to_call, nr_calls); + rcu_read_unlock(); + return ret; +} + +EXPORT_SYMBOL_GPL(__tunable_atomic_notifier_call_chain); + +int __kprobes tunable_atomic_notifier_call_chain( + struct tunable_atomic_notifier_head *nh, + unsigned long val, void *v) +{ + return __tunable_atomic_notifier_call_chain(nh, val, v, -1, NULL); +} + +EXPORT_SYMBOL_GPL(tunable_atomic_notifier_call_chain); + +/* * Raw notifier chain routines. There is no protection; * the caller must provide it. Use at your own risk! */ ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 1/2] add tunable_notifier function ,take2 2007-10-18 8:53 ` Takenori Nagano @ 2007-10-24 18:16 ` Randy Dunlap -1 siblings, 0 replies; 14+ messages in thread From: Randy Dunlap @ 2007-10-24 18:16 UTC (permalink / raw) To: Takenori Nagano Cc: k-miyoshi, Bernhard Walle, kdb, kexec, linux-kernel, vgoyal, Eric W. Biederman, Keith Owens, Andrew Morton On Thu, 18 Oct 2007 17:53:00 +0900 Takenori Nagano wrote: > This patch adds new notifier function tunable_notifier_chain. Its base is > atomic_notifier_chain. > > Thanks, > > --- > > Signed-off-by: Takenori Nagano <t-nagano@ah.jp.nec.com> > > --- > diff -uprN linux-2.6.23.orig/kernel/sys.c linux-2.6.23/kernel/sys.c > --- linux-2.6.23.orig/kernel/sys.c 2007-10-10 05:31:38.000000000 +0900 > +++ linux-2.6.23/kernel/sys.c 2007-10-18 10:08:52.728000000 +0900 > @@ -38,6 +38,7 @@ > #include <linux/syscalls.h> > #include <linux/kprobes.h> > #include <linux/user_namespace.h> > +#include <linux/debugfs.h> > > #include <asm/uaccess.h> > #include <asm/io.h> > @@ -393,6 +394,243 @@ int blocking_notifier_call_chain(struct > EXPORT_SYMBOL_GPL(blocking_notifier_call_chain); > +/** > + * tunable_atomic_notifier_chain_register > + * - Add notifier to an tunable notifier chain Function name & short description must be on one (long?) line. :( > + * @nh: Pointer to head of the tunable notifier chain > + * @n: New entry in notifier chain > + * @name: Pointer to the name of the new notifier entry > + * @desc: Pointer to the description of new entry > + * > + * Adds a notifier to an tunable notifier chain and makes control dir. > + * > + * Returns zero on success or %-ENODEV on failure. > + */ > + > +int tunable_atomic_notifier_chain_register( > + struct tunable_atomic_notifier_head *nh, > + struct tunable_atomic_notifier_block *n, char *name, char *desc) > +{ > +} > + > +EXPORT_SYMBOL_GPL(tunable_atomic_notifier_chain_register); > + > +/** > + * tunable_atomic_notifier_chain_unregister > + * - Remove notifier from a tunable notifier chain Ditto. > + * @nh: Pointer to head of the tunable notifier chain > + * @n: Entry to remove from notifier chain > + * > + * Removes a notifier from a tunable notifier chain. > + * > + * Retunrns zero on success or %-ENOENT on failure. > + */ > + > +int tunable_atomic_notifier_chain_unregister( > + struct tunable_atomic_notifier_head *nh, > + struct tunable_atomic_notifier_block *n) > +{ > +} > + > +EXPORT_SYMBOL_GPL(tunable_atomic_notifier_chain_unregister); > + > +/** > + * __tunable_atomic_notifier_call_chain > + * - Call functions in a tunable notifier chain Same. > + * @nh: Pointer to head of the tunable notifier chain > + * @val: Value passed unmodified to notifier function > + * @v: Pointer passed unmodified to notifier function > + * @nt_to_call: See the comment for notifier_call_chain @nr_to_call: ... > + * @nr_calls: See the comment for notifier_call_chain > + * > + * Calls each function in a notifier chain in turn. The functions > + * run in an atomic context, so they must not block. > + * This routine uses RCU to synchronize with changes to the chain. > + * > + * If the return value of the notifier can be and'ed > + * with %NOTIFY_STOP_MASK then tunable_atomic_notifier_call_chain() > + * will return immediately, with the return value of > + * the notifier function which halted execution. > + * Otherwise the return value is the return value > + * of the last notifier function called. > + */ > + > +int __kprobes __tunable_atomic_notifier_call_chain( > + struct tunable_atomic_notifier_head *nh, > + unsigned long val, void *v, > + int nr_to_call, int *nr_calls) > +{ > + int ret; > + > + rcu_read_lock(); > + ret = notifier_call_chain(&nh->head, val, v, nr_to_call, nr_calls); > + rcu_read_unlock(); > + return ret; > +} > + > +EXPORT_SYMBOL_GPL(__tunable_atomic_notifier_call_chain); Blank line is usually omitted before EXPORT_SYMBOL.... --- ~Randy _______________________________________________ kexec mailing list kexec@lists.infradead.org http://lists.infradead.org/mailman/listinfo/kexec ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 1/2] add tunable_notifier function ,take2 @ 2007-10-24 18:16 ` Randy Dunlap 0 siblings, 0 replies; 14+ messages in thread From: Randy Dunlap @ 2007-10-24 18:16 UTC (permalink / raw) To: Takenori Nagano Cc: linux-kernel, vgoyal, Eric W. Biederman, k-miyoshi, kexec, Bernhard Walle, Keith Owens, Andrew Morton, kdb On Thu, 18 Oct 2007 17:53:00 +0900 Takenori Nagano wrote: > This patch adds new notifier function tunable_notifier_chain. Its base is > atomic_notifier_chain. > > Thanks, > > --- > > Signed-off-by: Takenori Nagano <t-nagano@ah.jp.nec.com> > > --- > diff -uprN linux-2.6.23.orig/kernel/sys.c linux-2.6.23/kernel/sys.c > --- linux-2.6.23.orig/kernel/sys.c 2007-10-10 05:31:38.000000000 +0900 > +++ linux-2.6.23/kernel/sys.c 2007-10-18 10:08:52.728000000 +0900 > @@ -38,6 +38,7 @@ > #include <linux/syscalls.h> > #include <linux/kprobes.h> > #include <linux/user_namespace.h> > +#include <linux/debugfs.h> > > #include <asm/uaccess.h> > #include <asm/io.h> > @@ -393,6 +394,243 @@ int blocking_notifier_call_chain(struct > EXPORT_SYMBOL_GPL(blocking_notifier_call_chain); > +/** > + * tunable_atomic_notifier_chain_register > + * - Add notifier to an tunable notifier chain Function name & short description must be on one (long?) line. :( > + * @nh: Pointer to head of the tunable notifier chain > + * @n: New entry in notifier chain > + * @name: Pointer to the name of the new notifier entry > + * @desc: Pointer to the description of new entry > + * > + * Adds a notifier to an tunable notifier chain and makes control dir. > + * > + * Returns zero on success or %-ENODEV on failure. > + */ > + > +int tunable_atomic_notifier_chain_register( > + struct tunable_atomic_notifier_head *nh, > + struct tunable_atomic_notifier_block *n, char *name, char *desc) > +{ > +} > + > +EXPORT_SYMBOL_GPL(tunable_atomic_notifier_chain_register); > + > +/** > + * tunable_atomic_notifier_chain_unregister > + * - Remove notifier from a tunable notifier chain Ditto. > + * @nh: Pointer to head of the tunable notifier chain > + * @n: Entry to remove from notifier chain > + * > + * Removes a notifier from a tunable notifier chain. > + * > + * Retunrns zero on success or %-ENOENT on failure. > + */ > + > +int tunable_atomic_notifier_chain_unregister( > + struct tunable_atomic_notifier_head *nh, > + struct tunable_atomic_notifier_block *n) > +{ > +} > + > +EXPORT_SYMBOL_GPL(tunable_atomic_notifier_chain_unregister); > + > +/** > + * __tunable_atomic_notifier_call_chain > + * - Call functions in a tunable notifier chain Same. > + * @nh: Pointer to head of the tunable notifier chain > + * @val: Value passed unmodified to notifier function > + * @v: Pointer passed unmodified to notifier function > + * @nt_to_call: See the comment for notifier_call_chain @nr_to_call: ... > + * @nr_calls: See the comment for notifier_call_chain > + * > + * Calls each function in a notifier chain in turn. The functions > + * run in an atomic context, so they must not block. > + * This routine uses RCU to synchronize with changes to the chain. > + * > + * If the return value of the notifier can be and'ed > + * with %NOTIFY_STOP_MASK then tunable_atomic_notifier_call_chain() > + * will return immediately, with the return value of > + * the notifier function which halted execution. > + * Otherwise the return value is the return value > + * of the last notifier function called. > + */ > + > +int __kprobes __tunable_atomic_notifier_call_chain( > + struct tunable_atomic_notifier_head *nh, > + unsigned long val, void *v, > + int nr_to_call, int *nr_calls) > +{ > + int ret; > + > + rcu_read_lock(); > + ret = notifier_call_chain(&nh->head, val, v, nr_to_call, nr_calls); > + rcu_read_unlock(); > + return ret; > +} > + > +EXPORT_SYMBOL_GPL(__tunable_atomic_notifier_call_chain); Blank line is usually omitted before EXPORT_SYMBOL.... --- ~Randy ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 1/2] add tunable_notifier function ,take2 2007-10-24 18:16 ` Randy Dunlap @ 2007-10-25 8:02 ` Takenori Nagano -1 siblings, 0 replies; 14+ messages in thread From: Takenori Nagano @ 2007-10-25 8:02 UTC (permalink / raw) To: Randy Dunlap Cc: k-miyoshi, Bernhard Walle, kdb, kexec, linux-kernel, vgoyal, Eric W. Biederman, Keith Owens, Andrew Morton Randy Dunlap wrote: > On Thu, 18 Oct 2007 17:53:00 +0900 Takenori Nagano wrote: > >> This patch adds new notifier function tunable_notifier_chain. Its base is >> atomic_notifier_chain. >> >> Thanks, >> >> --- >> >> Signed-off-by: Takenori Nagano <t-nagano@ah.jp.nec.com> >> >> --- >> diff -uprN linux-2.6.23.orig/kernel/sys.c linux-2.6.23/kernel/sys.c >> --- linux-2.6.23.orig/kernel/sys.c 2007-10-10 05:31:38.000000000 +0900 >> +++ linux-2.6.23/kernel/sys.c 2007-10-18 10:08:52.728000000 +0900 >> @@ -38,6 +38,7 @@ >> #include <linux/syscalls.h> >> #include <linux/kprobes.h> >> #include <linux/user_namespace.h> >> +#include <linux/debugfs.h> >> >> #include <asm/uaccess.h> >> #include <asm/io.h> >> @@ -393,6 +394,243 @@ int blocking_notifier_call_chain(struct >> EXPORT_SYMBOL_GPL(blocking_notifier_call_chain); > >> +/** >> + * tunable_atomic_notifier_chain_register >> + * - Add notifier to an tunable notifier chain > > Function name & short description must be on one (long?) line. :( OK. I'll fix next version. >> + >> +int __kprobes __tunable_atomic_notifier_call_chain( >> + struct tunable_atomic_notifier_head *nh, >> + unsigned long val, void *v, >> + int nr_to_call, int *nr_calls) >> +{ >> + int ret; >> + >> + rcu_read_lock(); >> + ret = notifier_call_chain(&nh->head, val, v, nr_to_call, nr_calls); >> + rcu_read_unlock(); >> + return ret; >> +} >> + >> +EXPORT_SYMBOL_GPL(__tunable_atomic_notifier_call_chain); > > Blank line is usually omitted before EXPORT_SYMBOL.... OK. I'll fix, too. Thanks, Takenori > --- > ~Randy > > _______________________________________________ kexec mailing list kexec@lists.infradead.org http://lists.infradead.org/mailman/listinfo/kexec ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 1/2] add tunable_notifier function ,take2 @ 2007-10-25 8:02 ` Takenori Nagano 0 siblings, 0 replies; 14+ messages in thread From: Takenori Nagano @ 2007-10-25 8:02 UTC (permalink / raw) To: Randy Dunlap Cc: linux-kernel, vgoyal, Eric W. Biederman, k-miyoshi, kexec, Bernhard Walle, Keith Owens, Andrew Morton, kdb Randy Dunlap wrote: > On Thu, 18 Oct 2007 17:53:00 +0900 Takenori Nagano wrote: > >> This patch adds new notifier function tunable_notifier_chain. Its base is >> atomic_notifier_chain. >> >> Thanks, >> >> --- >> >> Signed-off-by: Takenori Nagano <t-nagano@ah.jp.nec.com> >> >> --- >> diff -uprN linux-2.6.23.orig/kernel/sys.c linux-2.6.23/kernel/sys.c >> --- linux-2.6.23.orig/kernel/sys.c 2007-10-10 05:31:38.000000000 +0900 >> +++ linux-2.6.23/kernel/sys.c 2007-10-18 10:08:52.728000000 +0900 >> @@ -38,6 +38,7 @@ >> #include <linux/syscalls.h> >> #include <linux/kprobes.h> >> #include <linux/user_namespace.h> >> +#include <linux/debugfs.h> >> >> #include <asm/uaccess.h> >> #include <asm/io.h> >> @@ -393,6 +394,243 @@ int blocking_notifier_call_chain(struct >> EXPORT_SYMBOL_GPL(blocking_notifier_call_chain); > >> +/** >> + * tunable_atomic_notifier_chain_register >> + * - Add notifier to an tunable notifier chain > > Function name & short description must be on one (long?) line. :( OK. I'll fix next version. >> + >> +int __kprobes __tunable_atomic_notifier_call_chain( >> + struct tunable_atomic_notifier_head *nh, >> + unsigned long val, void *v, >> + int nr_to_call, int *nr_calls) >> +{ >> + int ret; >> + >> + rcu_read_lock(); >> + ret = notifier_call_chain(&nh->head, val, v, nr_to_call, nr_calls); >> + rcu_read_unlock(); >> + return ret; >> +} >> + >> +EXPORT_SYMBOL_GPL(__tunable_atomic_notifier_call_chain); > > Blank line is usually omitted before EXPORT_SYMBOL.... OK. I'll fix, too. Thanks, Takenori > --- > ~Randy > > ^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2008-04-11 19:56 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <47FF0EA5.8090804@ah.jp.nec.com>
2008-04-11 7:53 ` [PATCH 1/2] add tunable_notifier function ,take2 Takenori Nagano
2008-04-11 7:53 ` Takenori Nagano
2008-04-11 19:55 ` Greg KH
2008-04-11 19:55 ` Greg KH
2008-04-11 7:53 ` [PATCH 2/2] implement new notifier function to panic_notifier_list ,take3 Takenori Nagano
2008-04-11 7:53 ` Takenori Nagano
[not found] <4716FFDB.7090502@ah.jp.nec.com>
2007-10-18 6:45 ` [PATCH 1/2] add tunable_notifier function ,take2 Takenori Nagano
2007-10-18 6:45 ` Takenori Nagano
2007-10-18 8:53 ` Takenori Nagano
2007-10-18 8:53 ` Takenori Nagano
2007-10-24 18:16 ` Randy Dunlap
2007-10-24 18:16 ` Randy Dunlap
2007-10-25 8:02 ` Takenori Nagano
2007-10-25 8:02 ` Takenori Nagano
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.