Received: by 2002:a25:868d:0:0:0:0:0 with SMTP id z13csp813309ybk; Wed, 13 May 2020 13:53:18 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxx7CnAMvRN135wiY1jQB9aYbTPxgsuqm/8vLc3YiicCa2WsN5RQsCumhjXqg/yOpSCA9ka X-Received: by 2002:a17:906:7e15:: with SMTP id e21mr896205ejr.106.1589403197880; Wed, 13 May 2020 13:53:17 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1589403197; cv=none; d=google.com; s=arc-20160816; b=J/Fp3nZHf+sdekLBUls8erVKIKnK/ssP4iADb2IHUCbylGZFtugGVVSqiGH8jIBu7T UeOF/bS82QaW8wHK21YFsFjvE74dQ8aDz4uuKBZv2LR0iuT1zyKL4ZBICSu3ApWRMA0D cBOebetf4Le2bbkN3Asiys02S+XFxszTC9jB8FhTuW6IbSVyqYwIM7jR61x/qAosCuUb 9qVrfwZDc/O8tjmSlJTKdRg4ByDHwXEDWNJqzXPfFd36T4E42Wc/0Kk1d9egUcAU6bwv mt6ixbH8Vlyi/eh7YwDLRijU1QxzrSoJEcwj7PsoaYQDFPDliUATtQpDNtIMrbLl78DC dikQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:user-agent:in-reply-to :content-disposition:mime-version:references:reply-to:message-id :subject:cc:to:from:date:dkim-signature; bh=S4QNqd8gM7vVXjS3rkB9OnAbopm9YZvLSb8etF2LMeM=; b=r9afpIZV6vkNrbEuDNR6HnLZalXZSJv57nqQhpInLlybwa0hMiLOtoBthumj5cw24l 7slomILrYwgxBs4lww7sSPNZegYifwwJIEvqP3a9T7HblyC81xT9iCU/sIohVLdWdHzS 1hH6gEmn16ibmMLXEGvh1i8wfETkq0vMAxOaBQCoi9t2u4nrUXh+6dPsdhPJtyWeu0bK f8azYf34w7R77fkJOsJTMBpY7wpPoPdvQlrvf1NMhAIsribpikWuJ6vYmdQWPE0As0c5 pFWtZgWi8ZB9GIUrBirD91U4kbw+d09ZEMMqG26f8w8/9cSz2WJtvutK90Jb/zy9Fj/l xUUw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=ozcDfSer; 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 cx2si439768edb.452.2020.05.13.13.52.54; Wed, 13 May 2020 13:53:17 -0700 (PDT) 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=default header.b=ozcDfSer; 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 S2390150AbgEMSid (ORCPT + 99 others); Wed, 13 May 2020 14:38:33 -0400 Received: from mail.kernel.org ([198.145.29.99]:52814 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730472AbgEMSic (ORCPT ); Wed, 13 May 2020 14:38:32 -0400 Received: from paulmck-ThinkPad-P72.home (unknown [50.39.105.78]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 07D73205CB; Wed, 13 May 2020 18:38:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1589395113; bh=H6DNcceGbM802VFUoTzNjNzUOuJV1jrZ0ied7e4iMcw=; h=Date:From:To:Cc:Subject:Reply-To:References:In-Reply-To:From; b=ozcDfSerOtx4FEyKJqnv77r/GyuiHS/fOHIyKNoxeFkYTwhc7aaLMaQJEtIEJeT0Z D5mGavQnQ1l2VPv8eT8PR9jIa8d5tfikC/tSMoECO62Ldp1C31f+a6vbC/3WEFBEv1 pDpuZ18eB6r5LAjfCwsdP7cUgHJh45DijuILb1ZE= Received: by paulmck-ThinkPad-P72.home (Postfix, from userid 1000) id B2CD9352352C; Wed, 13 May 2020 11:38:31 -0700 (PDT) Date: Wed, 13 May 2020 11:38:31 -0700 From: "Paul E. McKenney" To: Frederic Weisbecker Cc: LKML , Steven Rostedt , Mathieu Desnoyers , Lai Jiangshan , Joel Fernandes , Josh Triplett Subject: Re: [PATCH 08/10] rcu: Allow to deactivate nocb on a CPU Message-ID: <20200513183831.GV2869@paulmck-ThinkPad-P72> Reply-To: paulmck@kernel.org References: <20200513164714.22557-1-frederic@kernel.org> <20200513164714.22557-9-frederic@kernel.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20200513164714.22557-9-frederic@kernel.org> User-Agent: Mutt/1.9.4 (2018-02-28) Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Wed, May 13, 2020 at 06:47:12PM +0200, Frederic Weisbecker wrote: > Allow a CPU's rdp to quit the callback offlined mode. > The switch happens on the target with IRQs disabled and rdp->nocb_lock > held to avoid races between local callbacks handling and kthread > offloaded callbacks handling. > > nocb_cb kthread is first parked to avoid any future race with > concurrent rcu_do_batch() executions. Then the cblist is set to offloaded > so that the nocb_gp kthread ignores this rdp. > > Inspired-by: Paul E. McKenney > Signed-off-by: Frederic Weisbecker > Cc: Paul E. McKenney > Cc: Josh Triplett > Cc: Steven Rostedt > Cc: Mathieu Desnoyers > Cc: Lai Jiangshan > Cc: Joel Fernandes > --- > include/linux/rcupdate.h | 2 ++ > kernel/rcu/rcu_segcblist.c | 4 +-- > kernel/rcu/rcu_segcblist.h | 2 +- > kernel/rcu/tree_plugin.h | 50 +++++++++++++++++++++++++++++++++++++- > 4 files changed, 54 insertions(+), 4 deletions(-) > > diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h > index 2678a37c3169..1d3a4c37c3c1 100644 > --- a/include/linux/rcupdate.h > +++ b/include/linux/rcupdate.h > @@ -96,8 +96,10 @@ static inline void rcu_user_exit(void) { } > > #ifdef CONFIG_RCU_NOCB_CPU > void rcu_init_nohz(void); > +void rcu_nocb_cpu_deoffload(int cpu); > #else /* #ifdef CONFIG_RCU_NOCB_CPU */ > static inline void rcu_init_nohz(void) { } > +static inline void rcu_nocb_cpu_deoffload(int cpu) { } > #endif /* #else #ifdef CONFIG_RCU_NOCB_CPU */ > > /** > diff --git a/kernel/rcu/rcu_segcblist.c b/kernel/rcu/rcu_segcblist.c > index d8ea2bef5574..4bed48da7702 100644 > --- a/kernel/rcu/rcu_segcblist.c > +++ b/kernel/rcu/rcu_segcblist.c > @@ -171,9 +171,9 @@ void rcu_segcblist_disable(struct rcu_segcblist *rsclp) > * Mark the specified rcu_segcblist structure as offloaded. This > * structure must be empty. > */ > -void rcu_segcblist_offload(struct rcu_segcblist *rsclp) > +void rcu_segcblist_offload(struct rcu_segcblist *rsclp, bool offload) > { > - rsclp->offloaded = 1; > + rsclp->offloaded = offload; > } > #endif > > diff --git a/kernel/rcu/rcu_segcblist.h b/kernel/rcu/rcu_segcblist.h > index 4c1503a82492..8f7c6c34cb1b 100644 > --- a/kernel/rcu/rcu_segcblist.h > +++ b/kernel/rcu/rcu_segcblist.h > @@ -83,7 +83,7 @@ void rcu_segcblist_inc_len(struct rcu_segcblist *rsclp); > void rcu_segcblist_init(struct rcu_segcblist *rsclp); > void rcu_segcblist_disable(struct rcu_segcblist *rsclp); > #ifdef CONFIG_RCU_NOCB_CPU > -void rcu_segcblist_offload(struct rcu_segcblist *rsclp); > +void rcu_segcblist_offload(struct rcu_segcblist *rsclp, bool offload); > #endif > bool rcu_segcblist_ready_cbs(struct rcu_segcblist *rsclp); > bool rcu_segcblist_pend_cbs(struct rcu_segcblist *rsclp); > diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h > index f19e81e0c691..c74a4df8d5f2 100644 > --- a/kernel/rcu/tree_plugin.h > +++ b/kernel/rcu/tree_plugin.h > @@ -1943,6 +1943,10 @@ static void nocb_gp_wait(struct rcu_data *my_rdp) > for (rdp = my_rdp; rdp; rdp = rdp->nocb_next_cb_rdp) { > trace_rcu_nocb_wake(rcu_state.name, rdp->cpu, TPS("Check")); > raw_spin_lock_irqsave(&rdp->nocb_lock, flags); > + if (!rcu_segcblist_is_offloaded(&rdp->cblist)) { > + raw_spin_unlock_irqrestore(&rdp->nocb_lock, flags); > + continue; > + } > bypass_ncbs = rcu_cblist_n_cbs(&rdp->nocb_bypass); > if (bypass_ncbs && > (time_after(j, READ_ONCE(rdp->nocb_bypass_first) + 1) || > @@ -2176,6 +2180,50 @@ static void do_nocb_deferred_wakeup(struct rcu_data *rdp) > do_nocb_deferred_wakeup_common(rdp); > } > > +static void __rcu_nocb_rdp_deoffload(struct rcu_data *rdp) > +{ > + unsigned long flags; > + struct rcu_node *rnp = rdp->mynode; > + > + printk("De-offloading %d\n", rdp->cpu); > + kthread_park(rdp->nocb_cb_kthread); I am a bit concerned about this, because from this point until the end of this function, no RCU callbacks can be invoked for this CPU. This could be a problem if there is a callback flood in progress, and such callback floods are in fact one reason that the sysadm might want to be switching from offloaded to non-offloaded. Is it possible to move this kthread_park() to the end of this function? Yes, this can result in concurrent invocation of different callbacks for this CPU, but because we have excluded rcu_barrier(), that should be OK. Or is there some failure mode that I am failing to see? (Wouldn't be the first time...) > + raw_spin_lock_irqsave(&rdp->nocb_lock, flags); > + rcu_nocb_flush_bypass(rdp, NULL, jiffies); > + raw_spin_lock_rcu_node(rnp); > + rcu_segcblist_offload(&rdp->cblist, false); > + raw_spin_unlock_rcu_node(rnp); > + raw_spin_unlock_irqrestore(&rdp->nocb_lock, flags); > +} > + > +static long rcu_nocb_rdp_deoffload(void *arg) > +{ > + struct rcu_data *rdp = arg; > + > + WARN_ON_ONCE(rdp->cpu != raw_smp_processor_id()); > + __rcu_nocb_rdp_deoffload(rdp); > + > + return 0; > +} For example, is the problem caused by invocations of this rcu_nocb_rdp_deoffload() function? But if so, do we really need to acquire rcu_state.barrier_mutex? That aside, if it is possible to do the switch without interrupting callback invocation? Or is your idea that because we are always executing on the CPU being deoffloaded, that CPU has been prevented from posting callbacks in any case? If the latter, does that mean that it is not possible to deoffload offlined CPUs? (Not sure whether this restriction is a real problem, but figured that I should ask.) Thanx, Paul > +void rcu_nocb_cpu_deoffload(int cpu) > +{ > + struct rcu_data *rdp = per_cpu_ptr(&rcu_data, cpu); > + > + mutex_lock(&rcu_state.barrier_mutex); > + cpus_read_lock(); > + if (rcu_segcblist_is_offloaded(&rdp->cblist)) { > + if (cpu_online(cpu)) { > + work_on_cpu(cpu, rcu_nocb_rdp_deoffload, rdp); > + } else { > + __rcu_nocb_rdp_deoffload(rdp); > + } > + cpumask_clear_cpu(cpu, rcu_nocb_mask); > + } > + cpus_read_unlock(); > + mutex_unlock(&rcu_state.barrier_mutex); > +} > + > void __init rcu_init_nohz(void) > { > int cpu; > @@ -2218,7 +2266,7 @@ void __init rcu_init_nohz(void) > rdp = per_cpu_ptr(&rcu_data, cpu); > if (rcu_segcblist_empty(&rdp->cblist)) > rcu_segcblist_init(&rdp->cblist); > - rcu_segcblist_offload(&rdp->cblist); > + rcu_segcblist_offload(&rdp->cblist, true); > } > rcu_organize_nocb_kthreads(); > } > -- > 2.25.0 >