@@ -87,7 +87,7 @@ static void register_panic_notifier()
{
static struct notifier_block panic_notifier = {
.notifier_call = panic_handler,
- .next = NULL,
+ .list = LIST_HEAD_INIT(panic_notifier.list),
.priority = INT_MAX
};
atomic_notifier_chain_register(&panic_notifier_list, &panic_notifier);
@@ -898,7 +898,7 @@ static int notify_panic(struct notifier_block *self, unsigned long unused1,
static struct notifier_block panic_exit_notifier = {
.notifier_call = notify_panic,
- .next = NULL,
+ .list = LIST_HEAD_INIT(panic_exit_notifier.list),
.priority = 1
};
@@ -243,7 +243,7 @@ static int panic_exit(struct notifier_block *self, unsigned long unused1,
static struct notifier_block panic_exit_notifier = {
.notifier_call = panic_exit,
- .next = NULL,
+ .list = LIST_HEAD_INIT(panic_exit_notifier.list),
.priority = 0
};
@@ -85,7 +85,7 @@ static int tts_notify_reboot(struct notifier_block *this,
static struct notifier_block tts_notifier = {
.notifier_call = tts_notify_reboot,
- .next = NULL,
+ .list = LIST_HEAD_INIT(tts_notifier.list),
.priority = 0,
};
@@ -4473,7 +4473,7 @@ static int panic_event(struct notifier_block *this,
static struct notifier_block panic_block = {
.notifier_call = panic_event,
- .next = NULL,
+ .list = LIST_HEAD_INIT(panic_block.list),
.priority = 200 /* priority: INT_MAX >= x >= 0 */
};
@@ -1183,7 +1183,7 @@ static int wdog_reboot_handler(struct notifier_block *this,
static struct notifier_block wdog_reboot_notifier = {
.notifier_call = wdog_reboot_handler,
- .next = NULL,
+ .list = LIST_HEAD_INIT(wdog_reboot_notifier.list),
.priority = 0
};
@@ -1212,7 +1212,7 @@ static int wdog_panic_handler(struct notifier_block *this,
static struct notifier_block wdog_panic_notifier = {
.notifier_call = wdog_panic_handler,
- .next = NULL,
+ .list = LIST_HEAD_INIT(wdog_panic_notifier.list),
.priority = 150 /* priority: INT_MAX >= x >= 0 */
};
@@ -505,7 +505,7 @@ static int dcdbas_reboot_notify(struct notifier_block *nb, unsigned long code,
static struct notifier_block dcdbas_reboot_nb = {
.notifier_call = dcdbas_reboot_notify,
- .next = NULL,
+ .list = LIST_HEAD_INIT(dcdbas_reboot_nb.list),
.priority = INT_MIN
};
@@ -8437,7 +8437,7 @@ static int md_notify_reboot(struct notifier_block *this,
static struct notifier_block md_notifier = {
.notifier_call = md_notify_reboot,
- .next = NULL,
+ .list = LIST_HEAD_INIT(md_notifier.list),
.priority = INT_MAX, /* before any real devices */
};
@@ -197,7 +197,7 @@ static void igb_shutdown(struct pci_dev *);
static int igb_notify_dca(struct notifier_block *, unsigned long, void *);
static struct notifier_block dca_notifier = {
.notifier_call = igb_notify_dca,
- .next = NULL,
+ .list = LIST_HEAD_INIT(dca_notifier.list),
.priority = 0
};
#endif
@@ -124,7 +124,7 @@ static int ixgbe_notify_dca(struct notifier_block *, unsigned long event,
void *p);
static struct notifier_block dca_notifier = {
.notifier_call = ixgbe_notify_dca,
- .next = NULL,
+ .list = LIST_HEAD_INIT(dca_notifier.list),
.priority = 0
};
#endif
@@ -4197,7 +4197,7 @@ myri10ge_notify_dca(struct notifier_block *nb, unsigned long event, void *p)
static struct notifier_block myri10ge_dca_notifier = {
.notifier_call = myri10ge_notify_dca,
- .next = NULL,
+ .list = LIST_HEAD_INIT(myri10ge_dca_notifier.list),
.priority = 0,
};
#endif /* CONFIG_MYRI10GE_DCA */
@@ -313,7 +313,7 @@ static int viawget_suspend(struct pci_dev *pcid, pm_message_t state);
static int viawget_resume(struct pci_dev *pcid);
struct notifier_block device_notifier = {
.notifier_call = device_notify_reboot,
- .next = NULL,
+ .list = LIST_HEAD_INIT(device_notifier.list),
.priority = 0,
};
#endif
@@ -49,40 +49,40 @@
struct notifier_block {
int (*notifier_call)(struct notifier_block *, unsigned long, void *);
- struct notifier_block __rcu *next;
+ struct list_head list;
int priority;
};
struct atomic_notifier_head {
spinlock_t lock;
- struct notifier_block __rcu *head;
+ struct list_head list;
};
struct blocking_notifier_head {
struct rw_semaphore rwsem;
- struct notifier_block __rcu *head;
+ struct list_head list;
};
struct raw_notifier_head {
- struct notifier_block __rcu *head;
+ struct list_head list;
};
struct srcu_notifier_head {
struct mutex mutex;
struct srcu_struct srcu;
- struct notifier_block __rcu *head;
+ struct list_head list;
};
#define ATOMIC_INIT_NOTIFIER_HEAD(name) do { \
spin_lock_init(&(name)->lock); \
- (name)->head = NULL; \
+ INIT_LIST_HEAD(&(name)->list); \
} while (0)
#define BLOCKING_INIT_NOTIFIER_HEAD(name) do { \
init_rwsem(&(name)->rwsem); \
- (name)->head = NULL; \
+ INIT_LIST_HEAD(&(name)->list); \
} while (0)
#define RAW_INIT_NOTIFIER_HEAD(name) do { \
- (name)->head = NULL; \
+ INIT_LIST_HEAD(&(name)->list); \
} while (0)
/* srcu_notifier_heads must be initialized and cleaned up dynamically */
@@ -92,12 +92,13 @@ extern void srcu_init_notifier_head(struct srcu_notifier_head *nh);
#define ATOMIC_NOTIFIER_INIT(name) { \
.lock = __SPIN_LOCK_UNLOCKED(name.lock), \
- .head = NULL }
+ .list = LIST_HEAD_INIT(name.list) }
#define BLOCKING_NOTIFIER_INIT(name) { \
.rwsem = __RWSEM_INITIALIZER((name).rwsem), \
- .head = NULL }
+ .list = LIST_HEAD_INIT(name.list) }
#define RAW_NOTIFIER_INIT(name) { \
- .head = NULL }
+ .list = LIST_HEAD_INIT(name.list) }
+
/* srcu_notifier_heads cannot be initialized statically */
#define ATOMIC_NOTIFIER_HEAD(name) \
@@ -805,7 +805,7 @@ done:
static struct notifier_block dbg_reboot_notifier = {
.notifier_call = dbg_notify_reboot,
- .next = NULL,
+ .list = LIST_HEAD_INIT(dbg_reboot_notifier.list),
.priority = INT_MAX,
};
@@ -18,44 +18,48 @@ BLOCKING_NOTIFIER_HEAD(reboot_notifier_list);
* are layered on top of these, with appropriate locking added.
*/
-static int notifier_chain_register(struct notifier_block **nl,
+static int notifier_chain_register(struct list_head *nl,
struct notifier_block *n)
{
- while ((*nl) != NULL) {
- if (n->priority > (*nl)->priority)
+ struct notifier_block *cur;
+
+ list_for_each_entry(cur, nl, list) {
+ if (n->priority > cur->priority)
break;
- nl = &((*nl)->next);
}
- n->next = *nl;
- rcu_assign_pointer(*nl, n);
+
+ list_add_tail_rcu(&n->list, &cur->list);
return 0;
}
-static int notifier_chain_cond_register(struct notifier_block **nl,
+static int notifier_chain_cond_register(struct list_head *nl,
struct notifier_block *n)
{
- while ((*nl) != NULL) {
- if ((*nl) == n)
+ struct notifier_block *cur;
+
+ list_for_each_entry(cur, nl, list) {
+ if (cur == n)
return 0;
- if (n->priority > (*nl)->priority)
+ if (n->priority > cur->priority)
break;
- nl = &((*nl)->next);
}
- n->next = *nl;
- rcu_assign_pointer(*nl, n);
+
+ list_add_tail_rcu(&n->list, &cur->list);
return 0;
}
-static int notifier_chain_unregister(struct notifier_block **nl,
+static int notifier_chain_unregister(struct list_head *nl,
struct notifier_block *n)
{
- while ((*nl) != NULL) {
- if ((*nl) == n) {
- rcu_assign_pointer(*nl, n->next);
+ struct notifier_block *cur;
+
+ list_for_each_entry(cur, nl, list) {
+ if (cur == n) {
+ list_del_bidir_rcu(&cur->list);
return 0;
}
- nl = &((*nl)->next);
}
+
return -ENOENT;
}
@@ -71,22 +75,20 @@ static int notifier_chain_unregister(struct notifier_block **nl,
* @returns: notifier_call_chain returns the value returned by the
* last notifier function called.
*/
-static int __kprobes notifier_call_chain(struct notifier_block **nl,
+static int __kprobes notifier_call_chain(struct list_head *nl,
unsigned long val, void *v,
int nr_to_call, int *nr_calls)
{
int ret = NOTIFY_DONE;
- struct notifier_block *nb, *next_nb;
-
- nb = rcu_dereference_raw(*nl);
+ struct notifier_block *nb;
- while (nb && nr_to_call) {
- next_nb = rcu_dereference_raw(nb->next);
+ list_for_each_entry_rcu(nb, nl, list) {
+ if (!nr_to_call)
+ break;
#ifdef CONFIG_DEBUG_NOTIFIERS
if (unlikely(!func_ptr_is_kernel_text(nb->notifier_call))) {
WARN(1, "Invalid notifier called!");
- nb = next_nb;
continue;
}
#endif
@@ -97,9 +99,9 @@ static int __kprobes notifier_call_chain(struct notifier_block **nl,
if ((ret & NOTIFY_STOP_MASK) == NOTIFY_STOP_MASK)
break;
- nb = next_nb;
nr_to_call--;
}
+
return ret;
}
@@ -124,7 +126,7 @@ int atomic_notifier_chain_register(struct atomic_notifier_head *nh,
int ret;
spin_lock_irqsave(&nh->lock, flags);
- ret = notifier_chain_register(&nh->head, n);
+ ret = notifier_chain_register(&nh->list, n);
spin_unlock_irqrestore(&nh->lock, flags);
return ret;
}
@@ -146,7 +148,7 @@ int atomic_notifier_chain_unregister(struct atomic_notifier_head *nh,
int ret;
spin_lock_irqsave(&nh->lock, flags);
- ret = notifier_chain_unregister(&nh->head, n);
+ ret = notifier_chain_unregister(&nh->list, n);
spin_unlock_irqrestore(&nh->lock, flags);
synchronize_rcu();
return ret;
@@ -179,7 +181,7 @@ int __kprobes __atomic_notifier_call_chain(struct atomic_notifier_head *nh,
int ret;
rcu_read_lock();
- ret = notifier_call_chain(&nh->head, val, v, nr_to_call, nr_calls);
+ ret = notifier_call_chain(&nh->list, val, v, nr_to_call, nr_calls);
rcu_read_unlock();
return ret;
}
@@ -218,10 +220,10 @@ int blocking_notifier_chain_register(struct blocking_notifier_head *nh,
* such times we must not call down_write().
*/
if (unlikely(system_state == SYSTEM_BOOTING))
- return notifier_chain_register(&nh->head, n);
+ return notifier_chain_register(&nh->list, n);
down_write(&nh->rwsem);
- ret = notifier_chain_register(&nh->head, n);
+ ret = notifier_chain_register(&nh->list, n);
up_write(&nh->rwsem);
return ret;
}
@@ -244,7 +246,7 @@ int blocking_notifier_chain_cond_register(struct blocking_notifier_head *nh,
int ret;
down_write(&nh->rwsem);
- ret = notifier_chain_cond_register(&nh->head, n);
+ ret = notifier_chain_cond_register(&nh->list, n);
up_write(&nh->rwsem);
return ret;
}
@@ -271,10 +273,10 @@ int blocking_notifier_chain_unregister(struct blocking_notifier_head *nh,
* such times we must not call down_write().
*/
if (unlikely(system_state == SYSTEM_BOOTING))
- return notifier_chain_unregister(&nh->head, n);
+ return notifier_chain_unregister(&nh->list, n);
down_write(&nh->rwsem);
- ret = notifier_chain_unregister(&nh->head, n);
+ ret = notifier_chain_unregister(&nh->list, n);
up_write(&nh->rwsem);
return ret;
}
@@ -305,13 +307,14 @@ int __blocking_notifier_call_chain(struct blocking_notifier_head *nh,
int ret = NOTIFY_DONE;
/*
- * We check the head outside the lock, but if this access is
- * racy then it does not matter what the result of the test
- * is, we re-check the list after having taken the lock anyway:
+ * We check whether the list is empty outside the lock, but if
+ * this access is racy then it does not matter what the result
+ * of the test is, we re-check the list after having taken the
+ * lock anyway.
*/
- if (rcu_dereference_raw(nh->head)) {
+ if (!list_empty(&nh->list)) {
down_read(&nh->rwsem);
- ret = notifier_call_chain(&nh->head, val, v, nr_to_call,
+ ret = notifier_call_chain(&nh->list, val, v, nr_to_call,
nr_calls);
up_read(&nh->rwsem);
}
@@ -344,7 +347,7 @@ EXPORT_SYMBOL_GPL(blocking_notifier_call_chain);
int raw_notifier_chain_register(struct raw_notifier_head *nh,
struct notifier_block *n)
{
- return notifier_chain_register(&nh->head, n);
+ return notifier_chain_register(&nh->list, n);
}
EXPORT_SYMBOL_GPL(raw_notifier_chain_register);
@@ -361,7 +364,7 @@ EXPORT_SYMBOL_GPL(raw_notifier_chain_register);
int raw_notifier_chain_unregister(struct raw_notifier_head *nh,
struct notifier_block *n)
{
- return notifier_chain_unregister(&nh->head, n);
+ return notifier_chain_unregister(&nh->list, n);
}
EXPORT_SYMBOL_GPL(raw_notifier_chain_unregister);
@@ -388,7 +391,7 @@ int __raw_notifier_call_chain(struct raw_notifier_head *nh,
unsigned long val, void *v,
int nr_to_call, int *nr_calls)
{
- return notifier_call_chain(&nh->head, val, v, nr_to_call, nr_calls);
+ return notifier_call_chain(&nh->list, val, v, nr_to_call, nr_calls);
}
EXPORT_SYMBOL_GPL(__raw_notifier_call_chain);
@@ -425,10 +428,10 @@ int srcu_notifier_chain_register(struct srcu_notifier_head *nh,
* such times we must not call mutex_lock().
*/
if (unlikely(system_state == SYSTEM_BOOTING))
- return notifier_chain_register(&nh->head, n);
+ return notifier_chain_register(&nh->list, n);
mutex_lock(&nh->mutex);
- ret = notifier_chain_register(&nh->head, n);
+ ret = notifier_chain_register(&nh->list, n);
mutex_unlock(&nh->mutex);
return ret;
}
@@ -455,10 +458,10 @@ int srcu_notifier_chain_unregister(struct srcu_notifier_head *nh,
* such times we must not call mutex_lock().
*/
if (unlikely(system_state == SYSTEM_BOOTING))
- return notifier_chain_unregister(&nh->head, n);
+ return notifier_chain_unregister(&nh->list, n);
mutex_lock(&nh->mutex);
- ret = notifier_chain_unregister(&nh->head, n);
+ ret = notifier_chain_unregister(&nh->list, n);
mutex_unlock(&nh->mutex);
synchronize_srcu(&nh->srcu);
return ret;
@@ -491,7 +494,7 @@ int __srcu_notifier_call_chain(struct srcu_notifier_head *nh,
int idx;
idx = srcu_read_lock(&nh->srcu);
- ret = notifier_call_chain(&nh->head, val, v, nr_to_call, nr_calls);
+ ret = notifier_call_chain(&nh->list, val, v, nr_to_call, nr_calls);
srcu_read_unlock(&nh->srcu, idx);
return ret;
}
@@ -521,7 +524,7 @@ void srcu_init_notifier_head(struct srcu_notifier_head *nh)
mutex_init(&nh->mutex);
if (init_srcu_struct(&nh->srcu) < 0)
BUG();
- nh->head = NULL;
+ INIT_LIST_HEAD(&nh->list);
}
EXPORT_SYMBOL_GPL(srcu_init_notifier_head);
@@ -4876,7 +4876,7 @@ static int trace_panic_handler(struct notifier_block *this,
static struct notifier_block trace_panic_notifier = {
.notifier_call = trace_panic_handler,
- .next = NULL,
+ .list = LIST_HEAD_INIT(trace_panic_notifier.list),
.priority = 150 /* priority: INT_MAX >= x >= 0 */
};
@@ -1583,7 +1583,7 @@ ratelimit_handler(struct notifier_block *self, unsigned long u, void *v)
static struct notifier_block __cpuinitdata ratelimit_nb = {
.notifier_call = ratelimit_handler,
- .next = NULL,
+ .list = LIST_HEAD_INIT(ratelimit_nb.list),
};
/*
@@ -1196,8 +1196,8 @@ static int __cpuinit vmstat_cpuup_callback(struct notifier_block *nfb,
return NOTIFY_OK;
}
-static struct notifier_block __cpuinitdata vmstat_notifier =
- { &vmstat_cpuup_callback, NULL, 0 };
+static struct notifier_block __cpuinitdata vmstat_notifier = {
+ &vmstat_cpuup_callback, LIST_HEAD_INIT(vmstat_notifier.list), 0 };
#endif
static int __init setup_vmstat(void)
In order to support invoking the notifiers in the reverse order, we need to be able to traverse the callback chain in both directions. So convert the notifier list into a circular doubly linked list. Signed-off-by: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com> --- arch/mips/powertv/powertv_setup.c | 2 arch/um/drivers/mconsole_kern.c | 2 arch/um/kernel/um_arch.c | 2 drivers/acpi/sleep.c | 2 drivers/char/ipmi/ipmi_msghandler.c | 2 drivers/char/ipmi/ipmi_watchdog.c | 4 - drivers/firmware/dcdbas.c | 2 drivers/md/md.c | 2 drivers/net/ethernet/intel/igb/igb_main.c | 2 drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 2 drivers/net/ethernet/myricom/myri10ge/myri10ge.c | 2 drivers/staging/vt6655/device_main.c | 2 include/linux/notifier.h | 23 +++-- kernel/debug/debug_core.c | 2 kernel/notifier.c | 99 +++++++++++----------- kernel/trace/trace.c | 2 mm/page-writeback.c | 2 mm/vmstat.c | 4 - 18 files changed, 81 insertions(+), 77 deletions(-) -- To unsubscribe from this list: send the line "unsubscribe linux-pm" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html