lkml.org 
[lkml]   [2018]   [Jan]   [1]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.14 133/146] timers: Reinitialize per cpu bases on hotplug
    Date
    4.14-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Thomas Gleixner <tglx@linutronix.de>

    commit 26456f87aca7157c057de65c9414b37f1ab881d1 upstream.

    The timer wheel bases are not (re)initialized on CPU hotplug. That leaves
    them with a potentially stale clk and next_expiry valuem, which can cause
    trouble then the CPU is plugged.

    Add a prepare callback which forwards the clock, sets next_expiry to far in
    the future and reset the control flags to a known state.

    Set base->must_forward_clk so the first timer which is queued will try to
    forward the clock to current jiffies.

    Fixes: 500462a9de65 ("timers: Switch to a non-cascading wheel")
    Reported-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
    Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
    Cc: Peter Zijlstra <peterz@infradead.org>
    Cc: Frederic Weisbecker <fweisbec@gmail.com>
    Cc: Sebastian Siewior <bigeasy@linutronix.de>
    Cc: Anna-Maria Gleixner <anna-maria@linutronix.de>
    Link: https://lkml.kernel.org/r/alpine.DEB.2.20.1712272152200.2431@nanos
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    include/linux/cpuhotplug.h | 2 +-
    include/linux/timer.h | 4 +++-
    kernel/cpu.c | 4 ++--
    kernel/time/timer.c | 15 +++++++++++++++
    4 files changed, 21 insertions(+), 4 deletions(-)

    --- a/include/linux/cpuhotplug.h
    +++ b/include/linux/cpuhotplug.h
    @@ -86,7 +86,7 @@ enum cpuhp_state {
    CPUHP_MM_ZSWP_POOL_PREPARE,
    CPUHP_KVM_PPC_BOOK3S_PREPARE,
    CPUHP_ZCOMP_PREPARE,
    - CPUHP_TIMERS_DEAD,
    + CPUHP_TIMERS_PREPARE,
    CPUHP_MIPS_SOC_PREPARE,
    CPUHP_BP_PREPARE_DYN,
    CPUHP_BP_PREPARE_DYN_END = CPUHP_BP_PREPARE_DYN + 20,
    --- a/include/linux/timer.h
    +++ b/include/linux/timer.h
    @@ -246,9 +246,11 @@ unsigned long round_jiffies_up(unsigned
    unsigned long round_jiffies_up_relative(unsigned long j);

    #ifdef CONFIG_HOTPLUG_CPU
    +int timers_prepare_cpu(unsigned int cpu);
    int timers_dead_cpu(unsigned int cpu);
    #else
    -#define timers_dead_cpu NULL
    +#define timers_prepare_cpu NULL
    +#define timers_dead_cpu NULL
    #endif

    #endif
    --- a/kernel/cpu.c
    +++ b/kernel/cpu.c
    @@ -1277,9 +1277,9 @@ static struct cpuhp_step cpuhp_bp_states
    * before blk_mq_queue_reinit_notify() from notify_dead(),
    * otherwise a RCU stall occurs.
    */
    - [CPUHP_TIMERS_DEAD] = {
    + [CPUHP_TIMERS_PREPARE] = {
    .name = "timers:dead",
    - .startup.single = NULL,
    + .startup.single = timers_prepare_cpu,
    .teardown.single = timers_dead_cpu,
    },
    /* Kicks the plugged cpu into life */
    --- a/kernel/time/timer.c
    +++ b/kernel/time/timer.c
    @@ -1801,6 +1801,21 @@ static void migrate_timer_list(struct ti
    }
    }

    +int timers_prepare_cpu(unsigned int cpu)
    +{
    + struct timer_base *base;
    + int b;
    +
    + for (b = 0; b < NR_BASES; b++) {
    + base = per_cpu_ptr(&timer_bases[b], cpu);
    + base->clk = jiffies;
    + base->next_expiry = base->clk + NEXT_TIMER_MAX_DELTA;
    + base->is_idle = false;
    + base->must_forward_clk = true;
    + }
    + return 0;
    +}
    +
    int timers_dead_cpu(unsigned int cpu)
    {
    struct timer_base *old_base;

    \
     
     \ /
      Last update: 2018-01-01 15:47    [W:4.754 / U:0.008 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site