提交 e6d4989a 编写于 作者: R Richard Weinberger 提交者: Thomas Gleixner

relayfs: Convert to hotplug state machine

Install the callbacks via the state machine. They are installed at run time but
relay_prepare_cpu() does not need to be invoked by the boot CPU because
relay_open() was not yet invoked and there are no pools that need to be created.
Signed-off-by: NRichard Weinberger <richard@nod.at>
Signed-off-by: NThomas Gleixner <tglx@linutronix.de>
Signed-off-by: NSebastian Andrzej Siewior <bigeasy@linutronix.de>
Reviewed-by: NSebastian Andrzej Siewior <bigeasy@linutronix.de>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: rt@linutronix.de
Cc: Andrew Morton <akpm@linux-foundation.org>
Link: http://lkml.kernel.org/r/20160818125731.27256-3-bigeasy@linutronix.deSigned-off-by: NThomas Gleixner <tglx@linutronix.de>
上级 017c59c0
...@@ -21,6 +21,7 @@ enum cpuhp_state { ...@@ -21,6 +21,7 @@ enum cpuhp_state {
CPUHP_PROFILE_PREPARE, CPUHP_PROFILE_PREPARE,
CPUHP_X2APIC_PREPARE, CPUHP_X2APIC_PREPARE,
CPUHP_SMPCFD_PREPARE, CPUHP_SMPCFD_PREPARE,
CPUHP_RELAY_PREPARE,
CPUHP_RCUTREE_PREP, CPUHP_RCUTREE_PREP,
CPUHP_NOTIFY_PREPARE, CPUHP_NOTIFY_PREPARE,
CPUHP_TIMERS_DEAD, CPUHP_TIMERS_DEAD,
......
...@@ -288,5 +288,11 @@ static inline void subbuf_start_reserve(struct rchan_buf *buf, ...@@ -288,5 +288,11 @@ static inline void subbuf_start_reserve(struct rchan_buf *buf,
*/ */
extern const struct file_operations relay_file_operations; extern const struct file_operations relay_file_operations;
#ifdef CONFIG_RELAY
int relay_prepare_cpu(unsigned int cpu);
#else
#define relay_prepare_cpu NULL
#endif
#endif /* _LINUX_RELAY_H */ #endif /* _LINUX_RELAY_H */
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include <linux/tick.h> #include <linux/tick.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/smpboot.h> #include <linux/smpboot.h>
#include <linux/relay.h>
#include <trace/events/power.h> #include <trace/events/power.h>
#define CREATE_TRACE_POINTS #define CREATE_TRACE_POINTS
...@@ -1272,6 +1273,11 @@ static struct cpuhp_step cpuhp_bp_states[] = { ...@@ -1272,6 +1273,11 @@ static struct cpuhp_step cpuhp_bp_states[] = {
.startup.single = smpcfd_prepare_cpu, .startup.single = smpcfd_prepare_cpu,
.teardown.single = smpcfd_dead_cpu, .teardown.single = smpcfd_dead_cpu,
}, },
[CPUHP_RELAY_PREPARE] = {
.name = "relay:prepare",
.startup.single = relay_prepare_cpu,
.teardown.single = NULL,
},
[CPUHP_RCUTREE_PREP] = { [CPUHP_RCUTREE_PREP] = {
.name = "RCU/tree:prepare", .name = "RCU/tree:prepare",
.startup.single = rcutree_prepare_cpu, .startup.single = rcutree_prepare_cpu,
......
...@@ -513,48 +513,25 @@ static void setup_callbacks(struct rchan *chan, ...@@ -513,48 +513,25 @@ static void setup_callbacks(struct rchan *chan,
chan->cb = cb; chan->cb = cb;
} }
/** int relay_prepare_cpu(unsigned int cpu)
* relay_hotcpu_callback - CPU hotplug callback
* @nb: notifier block
* @action: hotplug action to take
* @hcpu: CPU number
*
* Returns the success/failure of the operation. (%NOTIFY_OK, %NOTIFY_BAD)
*/
static int relay_hotcpu_callback(struct notifier_block *nb,
unsigned long action,
void *hcpu)
{ {
unsigned int hotcpu = (unsigned long)hcpu;
struct rchan *chan; struct rchan *chan;
struct rchan_buf *buf; struct rchan_buf *buf;
switch(action) { mutex_lock(&relay_channels_mutex);
case CPU_UP_PREPARE: list_for_each_entry(chan, &relay_channels, list) {
case CPU_UP_PREPARE_FROZEN: if ((buf = *per_cpu_ptr(chan->buf, cpu)))
mutex_lock(&relay_channels_mutex); continue;
list_for_each_entry(chan, &relay_channels, list) { buf = relay_open_buf(chan, cpu);
if ((buf = *per_cpu_ptr(chan->buf, hotcpu))) if (!buf) {
continue; pr_err("relay: cpu %d buffer creation failed\n", cpu);
buf = relay_open_buf(chan, hotcpu); mutex_unlock(&relay_channels_mutex);
if (!buf) { return -ENOMEM;
printk(KERN_ERR
"relay_hotcpu_callback: cpu %d buffer "
"creation failed\n", hotcpu);
mutex_unlock(&relay_channels_mutex);
return notifier_from_errno(-ENOMEM);
}
*per_cpu_ptr(chan->buf, hotcpu) = buf;
} }
mutex_unlock(&relay_channels_mutex); *per_cpu_ptr(chan->buf, cpu) = buf;
break;
case CPU_DEAD:
case CPU_DEAD_FROZEN:
/* No need to flush the cpu : will be flushed upon
* final relay_flush() call. */
break;
} }
return NOTIFY_OK; mutex_unlock(&relay_channels_mutex);
return 0;
} }
/** /**
...@@ -1387,12 +1364,3 @@ const struct file_operations relay_file_operations = { ...@@ -1387,12 +1364,3 @@ const struct file_operations relay_file_operations = {
.splice_read = relay_file_splice_read, .splice_read = relay_file_splice_read,
}; };
EXPORT_SYMBOL_GPL(relay_file_operations); EXPORT_SYMBOL_GPL(relay_file_operations);
static __init int relay_init(void)
{
hotcpu_notifier(relay_hotcpu_callback, 0);
return 0;
}
early_initcall(relay_init);
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册