]> git.proxmox.com Git - mirror_ubuntu-focal-kernel.git/commitdiff
srcu: Apply *_ONCE() to ->srcu_last_gp_end
authorPaul E. McKenney <paulmck@kernel.org>
Mon, 4 Nov 2019 16:08:30 +0000 (08:08 -0800)
committerPaolo Pisati <paolo.pisati@canonical.com>
Mon, 17 Feb 2020 09:57:37 +0000 (10:57 +0100)
BugLink: https://bugs.launchpad.net/bugs/1863588
commit 844a378de3372c923909681706d62336d702531e upstream.

The ->srcu_last_gp_end field is accessed from any CPU at any time
by synchronize_srcu(), so non-initialization references need to use
READ_ONCE() and WRITE_ONCE().  This commit therefore makes that change.

Reported-by: syzbot+08f3e9d26e5541e1ecf2@syzkaller.appspotmail.com
Acked-by: Marco Elver <elver@google.com>
Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Paolo Pisati <paolo.pisati@canonical.com>
kernel/rcu/srcutree.c

index 5dffade2d7cd03b05007adca298a141184cd4551..21acdff3bd2781c2c5db125287172127472a6a3f 100644 (file)
@@ -530,7 +530,7 @@ static void srcu_gp_end(struct srcu_struct *ssp)
        idx = rcu_seq_state(ssp->srcu_gp_seq);
        WARN_ON_ONCE(idx != SRCU_STATE_SCAN2);
        cbdelay = srcu_get_delay(ssp);
-       ssp->srcu_last_gp_end = ktime_get_mono_fast_ns();
+       WRITE_ONCE(ssp->srcu_last_gp_end, ktime_get_mono_fast_ns());
        rcu_seq_end(&ssp->srcu_gp_seq);
        gpseq = rcu_seq_current(&ssp->srcu_gp_seq);
        if (ULONG_CMP_LT(ssp->srcu_gp_seq_needed_exp, gpseq))
@@ -762,6 +762,7 @@ static bool srcu_might_be_idle(struct srcu_struct *ssp)
        unsigned long flags;
        struct srcu_data *sdp;
        unsigned long t;
+       unsigned long tlast;
 
        /* If the local srcu_data structure has callbacks, not idle.  */
        local_irq_save(flags);
@@ -780,9 +781,9 @@ static bool srcu_might_be_idle(struct srcu_struct *ssp)
 
        /* First, see if enough time has passed since the last GP. */
        t = ktime_get_mono_fast_ns();
+       tlast = READ_ONCE(ssp->srcu_last_gp_end);
        if (exp_holdoff == 0 ||
-           time_in_range_open(t, ssp->srcu_last_gp_end,
-                              ssp->srcu_last_gp_end + exp_holdoff))
+           time_in_range_open(t, tlast, tlast + exp_holdoff))
                return false; /* Too soon after last GP. */
 
        /* Next, check for probable idleness. */