Received: by 2002:a05:6a10:8c0a:0:0:0:0 with SMTP id go10csp631843pxb; Wed, 24 Feb 2021 10:39:43 -0800 (PST) X-Google-Smtp-Source: ABdhPJzitqhCupcvK/Bf5ZeyUqmXDvL13XEaE8Btm4cGjvtTZGMG930pmXUkF+cmwWmeQyYTI44F X-Received: by 2002:a17:906:dff7:: with SMTP id lc23mr2061841ejc.211.1614191983683; Wed, 24 Feb 2021 10:39:43 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1614191983; cv=none; d=google.com; s=arc-20160816; b=yADARcbbipTVHAfBUF4P2BMzMe5JKfSZbPWvhrymLWrZJwKeGJ7fxHrhDJ0bQBFE5y OnYVMlX8HCLDkMggqXs0NYk2XIe3SP7ojD2cJZo0C5BtMgpTzGlF7P1+cS+WBfe8yTj+ t4tI+FD7SfB6YQKuk0B3FP3SklL0HxKCYyrpc4vA6fatjqajpqsaW1eHXWkPewvzUj2v Ylv5jfb9eaGCfmRzmBZkZdQpXLnm+U6ZkhaXAqAko2sGQkrlda0aSJQEIOQIMyWXTOFv 2jSsCHaDwuyfwul6pXQLGQ2rV7upWLmUg+VbH3zE3PS3hp9hS/R1ba0FlLEw4op1YnKA hAWw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:user-agent:in-reply-to:content-disposition :mime-version:references:reply-to:message-id:subject:cc:to:from:date :dkim-signature; bh=iCTTPpeKt68RPoxlOr/VthduUzkaGXPC6fuiZuQKE8g=; b=G2o0hhi47PZd82MB8WlvCaF+Yw6mWGN5ZohBVK6LP9cClt6xv+edj18J2dmYKrmpgZ 3q1MbdTf8p2cXwL1T7U62Cp5/eS1o+mytP3AsTlbwwPU1hUGiDHmquaRSq3ARH+txUsI YebdunnSLp0cWuz1R5Sk1azz4y7zDrHZAy6xKbzBDvVzPJdHOXq2u0afcElX49Z/ZUUd OoAS9U2m1gts2aC8kijyPVEDYl3kjfw3sNnYYcc5V4ZVI1QLeMPUqiW+qIegeOWZD1uk MoGp5di0ZS0fIt9TsNgNJfwBE1isK33BioEHGqqzH0SwfldmnnyWWayjtjOEiPJCLEUo gpdw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b="SCFD/lPy"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id o11si1797125eju.241.2021.02.24.10.39.19; Wed, 24 Feb 2021 10:39:43 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b="SCFD/lPy"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233136AbhBXShw (ORCPT + 99 others); Wed, 24 Feb 2021 13:37:52 -0500 Received: from mail.kernel.org ([198.145.29.99]:60688 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230494AbhBXShv (ORCPT ); Wed, 24 Feb 2021 13:37:51 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id D162464EFA; Wed, 24 Feb 2021 18:37:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1614191829; bh=oAYwh/6jkguj7oUJFr2rthanOZklrU7hUEqlB+XDtGg=; h=Date:From:To:Cc:Subject:Reply-To:References:In-Reply-To:From; b=SCFD/lPyMC5k28mEX01AgV4kJL+pVIJuJZ84PGqvlg4z9Quu/7SBssi3O05Q6LEWN rohgTrxeOX8Nwhc95OFrxBuEixfn+pEjWz4u3ATFMQD3dlQYuk8pn7RsWt6S9FeyhJ w3jJ5BEQ2eAvU5g4nBHAIKhnYGAkYZmz+nl82o9tLwqJ5Cl+FCIymke+EVfE0PiKYM v7HEceiYiFNHLgb+5doxQnVYGxe0e/2ru1hEi9YNOaGCcQXTijvWlCvYaxYfrMnEmA Cuw8xRhHxKOYhQUynJc7kt+ddkXWKcMlsSZH4KhjRJ+05dEtR5KaiVBr3twlLxwXz8 G4kjuQWYccBqg== Received: by paulmck-ThinkPad-P72.home (Postfix, from userid 1000) id 5AA7235229C6; Wed, 24 Feb 2021 10:37:09 -0800 (PST) Date: Wed, 24 Feb 2021 10:37:09 -0800 From: "Paul E. McKenney" To: Frederic Weisbecker Cc: LKML , Thomas Gleixner , Boqun Feng , Lai Jiangshan , Neeraj Upadhyay , Josh Triplett , Stable , Joel Fernandes Subject: Re: [PATCH 01/13] rcu/nocb: Fix potential missed nocb_timer rearm Message-ID: <20210224183709.GI2743@paulmck-ThinkPad-P72> Reply-To: paulmck@kernel.org References: <20210223001011.127063-1-frederic@kernel.org> <20210223001011.127063-2-frederic@kernel.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20210223001011.127063-2-frederic@kernel.org> User-Agent: Mutt/1.9.4 (2018-02-28) Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Tue, Feb 23, 2021 at 01:09:59AM +0100, Frederic Weisbecker wrote: > Two situations can cause a missed nocb timer rearm: > > 1) rdp(CPU A) queues its nocb timer. The grace period elapses before > the timer get a chance to fire. The nocb_gp kthread is awaken by > rdp(CPU B). The nocb_cb kthread for rdp(CPU A) is awaken and > process the callbacks, again before the nocb_timer for CPU A get a > chance to fire. rdp(CPU A) queues a callback and wakes up nocb_gp > kthread, cancelling the pending nocb_timer without resetting the > corresponding nocb_defer_wakeup. As discussed offlist, expanding the above scenario results in this sequence of steps: 1. There are no callbacks queued for any CPU covered by CPU 0-2's ->nocb_gp_kthread. 2. CPU 0 enqueues its first callback with interrupts disabled, and thus must defer awakening its ->nocb_gp_kthread. It therefore queues its rcu_data structure's ->nocb_timer. 3. CPU 1, which shares the same ->nocb_gp_kthread, also enqueues a callback, but with interrupts enabled, allowing it to directly awaken the ->nocb_gp_kthread. 4. The newly awakened ->nocb_gp_kthread associates both CPU 0's and CPU 1's callbacks with a future grace period and arranges for that grace period to be started. 5. This ->nocb_gp_kthread goes to sleep waiting for the end of this future grace period. 6. This grace period elapses before the CPU 0's timer fires. This is normally improbably given that the timer is set for only one jiffy, but timers can be delayed. Besides, it is possible that kernel was built with CONFIG_RCU_STRICT_GRACE_PERIOD=y. 7. The grace period ends, so rcu_gp_kthread awakens the ->nocb_gp_kthread, which in turn awakens both CPU 0's and CPU 1's ->nocb_cb_kthread. 8. CPU 0's ->nocb_cb_kthread invokes its callback. 9. Note that neither kthread updated any ->nocb_timer state, so CPU 0's ->nocb_defer_wakeup is still set to either RCU_NOCB_WAKE or RCU_NOCB_WAKE_FORCE. 10. CPU 0 enqueues its second callback, again with interrupts disabled, and thus must again defer awakening its ->nocb_gp_kthread. However, ->nocb_defer_wakeup prevents CPU 0 from queueing the timer. So far so good, but why isn't the timer still queued from back in step 2? What am I missing here? Either way, could you please update the commit logs to tell the full story? At some later time, you might be very happy that you did. ;-) Thanx, Paul > 2) The "nocb_bypass_timer" ends up calling wake_nocb_gp() which deletes > the pending "nocb_timer" (note they are not the same timers) for the > given rdp without resetting the matching state stored in nocb_defer > wakeup. > > On both situations, a future call_rcu() on that rdp may be fooled and > think the timer is armed when it's not, missing a deferred nocb_gp > wakeup. > > Case 1) is very unlikely due to timing constraint (the timer fires after > 1 jiffy) but still possible in theory. Case 2) is more likely to happen. > But in any case such scenario require the CPU to spend a long time > within a kernel thread without exiting to idle or user space, which is > a pretty exotic behaviour. > > Fix this with resetting rdp->nocb_defer_wakeup everytime we disarm the > timer. > > Fixes: d1b222c6be1f (rcu/nocb: Add bypass callback queueing) > Cc: Stable > Cc: Josh Triplett > Cc: Lai Jiangshan > Cc: Joel Fernandes > Cc: Neeraj Upadhyay > Cc: Boqun Feng > Signed-off-by: Frederic Weisbecker > --- > kernel/rcu/tree_plugin.h | 7 +++++-- > 1 file changed, 5 insertions(+), 2 deletions(-) > > diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h > index 2ec9d7f55f99..dd0dc66c282d 100644 > --- a/kernel/rcu/tree_plugin.h > +++ b/kernel/rcu/tree_plugin.h > @@ -1720,7 +1720,11 @@ static bool wake_nocb_gp(struct rcu_data *rdp, bool force, > rcu_nocb_unlock_irqrestore(rdp, flags); > return false; > } > - del_timer(&rdp->nocb_timer); > + > + if (READ_ONCE(rdp->nocb_defer_wakeup) > RCU_NOCB_WAKE_NOT) { > + WRITE_ONCE(rdp->nocb_defer_wakeup, RCU_NOCB_WAKE_NOT); > + del_timer(&rdp->nocb_timer); > + } > rcu_nocb_unlock_irqrestore(rdp, flags); > raw_spin_lock_irqsave(&rdp_gp->nocb_gp_lock, flags); > if (force || READ_ONCE(rdp_gp->nocb_gp_sleep)) { > @@ -2349,7 +2353,6 @@ static bool do_nocb_deferred_wakeup_common(struct rcu_data *rdp) > return false; > } > ndw = READ_ONCE(rdp->nocb_defer_wakeup); > - WRITE_ONCE(rdp->nocb_defer_wakeup, RCU_NOCB_WAKE_NOT); > ret = wake_nocb_gp(rdp, ndw == RCU_NOCB_WAKE_FORCE, flags); > trace_rcu_nocb_wake(rcu_state.name, rdp->cpu, TPS("DeferredWake")); > > -- > 2.25.1 >