[tip:smp/hotplug] relayfs: Convert to hotplug state machine

From: tip-bot for Richard Weinberger
Date: Tue Sep 06 2016 - 11:23:00 EST


Commit-ID: 0a02f95b4e94fd2908518763a367d64fe78dd4db
Gitweb: http://git.kernel.org/tip/0a02f95b4e94fd2908518763a367d64fe78dd4db
Author: Richard Weinberger <richard@xxxxxx>
AuthorDate: Thu, 18 Aug 2016 14:57:17 +0200
Committer: Thomas Gleixner <tglx@xxxxxxxxxxxxx>
CommitDate: Tue, 6 Sep 2016 16:20:28 +0200

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: Richard Weinberger <richard@xxxxxx>
Signed-off-by: Thomas Gleixner <tglx@xxxxxxxxxxxxx>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@xxxxxxxxxxxxx>
Reviewed-by: Sebastian Andrzej Siewior <bigeasy@xxxxxxxxxxxxx>
Cc: Peter Zijlstra <peterz@xxxxxxxxxxxxx>
Cc: rt@xxxxxxxxxxxxx
Cc: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx>
Link: http://lkml.kernel.org/r/20160818125731.27256-3-bigeasy@xxxxxxxxxxxxx
Signed-off-by: Thomas Gleixner <tglx@xxxxxxxxxxxxx>

---
include/linux/cpuhotplug.h | 1 +
include/linux/relay.h | 6 +++++
kernel/cpu.c | 6 +++++
kernel/relay.c | 58 +++++++++++-----------------------------------
4 files changed, 26 insertions(+), 45 deletions(-)

diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h
index 9e6d107..4c79f40 100644
--- a/include/linux/cpuhotplug.h
+++ b/include/linux/cpuhotplug.h
@@ -21,6 +21,7 @@ enum cpuhp_state {
CPUHP_PROFILE_PREPARE,
CPUHP_X2APIC_PREPARE,
CPUHP_SMPCFD_PREPARE,
+ CPUHP_RELAY_PREPARE,
CPUHP_RCUTREE_PREP,
CPUHP_NOTIFY_PREPARE,
CPUHP_TIMERS_DEAD,
diff --git a/include/linux/relay.h b/include/linux/relay.h
index eb295e3..ecbb34a 100644
--- a/include/linux/relay.h
+++ b/include/linux/relay.h
@@ -288,5 +288,11 @@ static inline void subbuf_start_reserve(struct rchan_buf *buf,
*/
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 */

diff --git a/kernel/cpu.c b/kernel/cpu.c
index d14ae44..09f66cc 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -23,6 +23,7 @@
#include <linux/tick.h>
#include <linux/irq.h>
#include <linux/smpboot.h>
+#include <linux/relay.h>

#include <trace/events/power.h>
#define CREATE_TRACE_POINTS
@@ -1272,6 +1273,11 @@ static struct cpuhp_step cpuhp_bp_states[] = {
.startup.single = smpcfd_prepare_cpu,
.teardown.single = smpcfd_dead_cpu,
},
+ [CPUHP_RELAY_PREPARE] = {
+ .name = "relay:prepare",
+ .startup = relay_prepare_cpu,
+ .teardown = NULL,
+ },
[CPUHP_RCUTREE_PREP] = {
.name = "RCU/tree:prepare",
.startup.single = rcutree_prepare_cpu,
diff --git a/kernel/relay.c b/kernel/relay.c
index ed15737..fc9b4a4 100644
--- a/kernel/relay.c
+++ b/kernel/relay.c
@@ -513,48 +513,25 @@ static void setup_callbacks(struct rchan *chan,
chan->cb = cb;
}

-/**
- * 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)
+int relay_prepare_cpu(unsigned int cpu)
{
- unsigned int hotcpu = (unsigned long)hcpu;
struct rchan *chan;
struct rchan_buf *buf;

- switch(action) {
- case CPU_UP_PREPARE:
- case CPU_UP_PREPARE_FROZEN:
- mutex_lock(&relay_channels_mutex);
- list_for_each_entry(chan, &relay_channels, list) {
- if ((buf = *per_cpu_ptr(chan->buf, hotcpu)))
- continue;
- buf = relay_open_buf(chan, hotcpu);
- if (!buf) {
- 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_lock(&relay_channels_mutex);
+ list_for_each_entry(chan, &relay_channels, list) {
+ if ((buf = *per_cpu_ptr(chan->buf, cpu)))
+ continue;
+ buf = relay_open_buf(chan, cpu);
+ if (!buf) {
+ pr_err("relay: cpu %d buffer creation failed\n", cpu);
+ mutex_unlock(&relay_channels_mutex);
+ return -ENOMEM;
}
- mutex_unlock(&relay_channels_mutex);
- break;
- case CPU_DEAD:
- case CPU_DEAD_FROZEN:
- /* No need to flush the cpu : will be flushed upon
- * final relay_flush() call. */
- break;
+ *per_cpu_ptr(chan->buf, cpu) = buf;
}
- return NOTIFY_OK;
+ mutex_unlock(&relay_channels_mutex);
+ return 0;
}

/**
@@ -1387,12 +1364,3 @@ const struct file_operations relay_file_operations = {
.splice_read = relay_file_splice_read,
};
EXPORT_SYMBOL_GPL(relay_file_operations);
-
-static __init int relay_init(void)
-{
-
- hotcpu_notifier(relay_hotcpu_callback, 0);
- return 0;
-}
-
-early_initcall(relay_init);