relayfs: Convert to hotplug state machine
authorRichard Weinberger <richard@nod.at>
Thu, 18 Aug 2016 12:57:17 +0000 (14:57 +0200)
committerThomas Gleixner <tglx@linutronix.de>
Tue, 6 Sep 2016 16:30:20 +0000 (18:30 +0200)
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@nod.at>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Reviewed-by: Sebastian 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.de
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
include/linux/cpuhotplug.h
include/linux/relay.h
kernel/cpu.c
kernel/relay.c

index 9e6d107..4c79f40 100644 (file)
@@ -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,
index eb295e3..ecbb34a 100644 (file)
@@ -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 */
 
index d14ae44..0c0d4b2 100644 (file)
@@ -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.single         = relay_prepare_cpu,
+               .teardown.single        = NULL,
+       },
        [CPUHP_RCUTREE_PREP] = {
                .name                   = "RCU/tree:prepare",
                .startup.single         = rcutree_prepare_cpu,
index ed15737..fc9b4a4 100644 (file)
@@ -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);