Received: by 2002:ac0:a5a6:0:0:0:0:0 with SMTP id m35-v6csp2522583imm; Mon, 24 Sep 2018 05:54:03 -0700 (PDT) X-Google-Smtp-Source: ACcGV61BbM8JdMWrcTm67lrFFAkF+gZzncQTuNMpbW7vzy+v7T/oHERtSrL+7FVbnYMgjTB27TgJ X-Received: by 2002:a63:1e19:: with SMTP id e25-v6mr1652439pge.44.1537793642954; Mon, 24 Sep 2018 05:54:02 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1537793642; cv=none; d=google.com; s=arc-20160816; b=zwAAb45obBr/R7AkOUAQ4zWtIr/qb4cnaa0F3MITi+HnMNc16pS16mkHPAhPFMbBTS gY7HTL2ZZervzYgoMxe+UYrOqqTWdWuYytnfpYnfSnWg9ViDFatcVc0R1oe99kN9+rUM kx/bv5bqEQ/lhQwpATxznTq8jfH83qXsaJXzluzPKlnFfcm+bb1A2mHywB6D1zWKfjeY dIDkZ9VxRgkx3SCXqZjPiAeXX5cjUSgnXLd4dJ/6jm5B7DUzqrCfX2J9RTpSgcbsvTE+ AvLllWL7Url9+6dy2RIhia6PLGpYHK8UgLawYzXLMJeaArL+wYcBn0Sd3bImoNc7T5MT X3FA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from; bh=tWjI2xrOXbQ41BjILuhRjJdvOjpiGjnzRHNJr02Y9Ug=; b=XsZbldrh3AVtFVZmbueL0BtyNVauxcRZdfgdB+up61vPE6wdfPPAGfXJKQFAKSgl5M kp5LPWafbnyTnqVwVDlPWkxUBuoiR4WwnLZbmmj1jo7Ee4oGbo1m6XE7wmkrOZERMVgi 6bY649b68k9KCQQ2fPYlAVB8AaDHIBoiYZH1legJ7d/+rlzFnjnzUF9hoYP+0R4IhdS4 hBMovR9SEWfO6/atzDE2L8U97cNr+3tkY81pKa3j7RRTaZagoBLbKTbWwLPgLNSNgRPz R6aMg9qZ3FJvlRYJA+XJPwvldtSP7rmIXusGpvPwq0SoLazFOqNqC+thS0gsbyCWDUzf 0fWg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 3-v6si35925490plu.65.2018.09.24.05.53.47; Mon, 24 Sep 2018 05:54:02 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1733109AbeIXS2Y (ORCPT + 99 others); Mon, 24 Sep 2018 14:28:24 -0400 Received: from mail.linuxfoundation.org ([140.211.169.12]:57124 "EHLO mail.linuxfoundation.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730649AbeIXS2X (ORCPT ); Mon, 24 Sep 2018 14:28:23 -0400 Received: from localhost (ip-213-127-77-73.ip.prioritytelecom.net [213.127.77.73]) by mail.linuxfoundation.org (Postfix) with ESMTPSA id 0CCE5108B; Mon, 24 Sep 2018 12:26:28 +0000 (UTC) From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, "Paul E. McKenney" , Sasha Levin Subject: [PATCH 4.14 146/173] rcu: Fix grace-period hangs due to race with CPU offline Date: Mon, 24 Sep 2018 13:53:00 +0200 Message-Id: <20180924113126.227036880@linuxfoundation.org> X-Mailer: git-send-email 2.19.0 In-Reply-To: <20180924113114.334025954@linuxfoundation.org> References: <20180924113114.334025954@linuxfoundation.org> User-Agent: quilt/0.65 X-stable: review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 4.14-stable review patch. If anyone has any objections, please let me know. ------------------ From: "Paul E. McKenney" [ Upstream commit 1e64b15a4b102e1cd059d4d798b7a78f93341333 ] Without special fail-safe quiescent-state-propagation checks, grace-period hangs can result from the following scenario: 1. CPU 1 goes offline. 2. Because CPU 1 is the only CPU in the system blocking the current grace period, the grace period ends as soon as rcu_cleanup_dying_idle_cpu()'s call to rcu_report_qs_rnp() returns. 3. At this point, the leaf rcu_node structure's ->lock is no longer held: rcu_report_qs_rnp() has released it, as it must in order to awaken the RCU grace-period kthread. 4. At this point, that same leaf rcu_node structure's ->qsmaskinitnext field still records CPU 1 as being online. This is absolutely necessary because the scheduler uses RCU (in this case on the wake-up path while awakening RCU's grace-period kthread), and ->qsmaskinitnext contains RCU's idea as to which CPUs are online. Therefore, invoking rcu_report_qs_rnp() after clearing CPU 1's bit from ->qsmaskinitnext would result in a lockdep-RCU splat due to RCU being used from an offline CPU. 5. RCU's grace-period kthread awakens, sees that the old grace period has completed and that a new one is needed. It therefore starts a new grace period, but because CPU 1's leaf rcu_node structure's ->qsmaskinitnext field still shows CPU 1 as being online, this new grace period is initialized to wait for a quiescent state from the now-offline CPU 1. 6. Without the fail-safe force-quiescent-state checks, there would be no quiescent state from the now-offline CPU 1, which would eventually result in RCU CPU stall warnings and memory exhaustion. It would be good to get rid of the special fail-safe quiescent-state propagation checks, and thus it would be good to fix things so that the above scenario cannot happen. This commit therefore adds a new ->ofl_lock to the rcu_state structure. This lock is held by rcu_gp_init() across the applying of buffered online and offline operations to the rcu_node tree, and it is also held by rcu_cleanup_dying_idle_cpu() when buffering a new offline operation. This prevents rcu_gp_init() from acquiring the leaf rcu_node structure's lock during the interval between when rcu_cleanup_dying_idle_cpu() invokes rcu_report_qs_rnp(), which releases ->lock and the re-acquisition of that same lock. This in turn prevents the failure scenario outlined above, and will hopefully eventually allow removal of the offline-CPU checks from the force-quiescent-state code path. Signed-off-by: Paul E. McKenney Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- kernel/rcu/tree.c | 6 ++++++ kernel/rcu/tree.h | 4 ++++ 2 files changed, 10 insertions(+) --- a/kernel/rcu/tree.c +++ b/kernel/rcu/tree.c @@ -102,6 +102,7 @@ struct rcu_state sname##_state = { \ .abbr = sabbr, \ .exp_mutex = __MUTEX_INITIALIZER(sname##_state.exp_mutex), \ .exp_wake_mutex = __MUTEX_INITIALIZER(sname##_state.exp_wake_mutex), \ + .ofl_lock = __SPIN_LOCK_UNLOCKED(sname##_state.ofl_lock), \ } RCU_STATE_INITIALIZER(rcu_sched, 's', call_rcu_sched); @@ -1996,11 +1997,13 @@ static bool rcu_gp_init(struct rcu_state */ rcu_for_each_leaf_node(rsp, rnp) { rcu_gp_slow(rsp, gp_preinit_delay); + spin_lock(&rsp->ofl_lock); raw_spin_lock_irq_rcu_node(rnp); if (rnp->qsmaskinit == rnp->qsmaskinitnext && !rnp->wait_blkd_tasks) { /* Nothing to do on this leaf rcu_node structure. */ raw_spin_unlock_irq_rcu_node(rnp); + spin_unlock(&rsp->ofl_lock); continue; } @@ -2035,6 +2038,7 @@ static bool rcu_gp_init(struct rcu_state } raw_spin_unlock_irq_rcu_node(rnp); + spin_unlock(&rsp->ofl_lock); } /* @@ -3837,9 +3841,11 @@ static void rcu_cleanup_dying_idle_cpu(i /* Remove outgoing CPU from mask in the leaf rcu_node structure. */ mask = rdp->grpmask; + spin_lock(&rsp->ofl_lock); raw_spin_lock_irqsave_rcu_node(rnp, flags); /* Enforce GP memory-order guarantee. */ rnp->qsmaskinitnext &= ~mask; raw_spin_unlock_irqrestore_rcu_node(rnp, flags); + spin_unlock(&rsp->ofl_lock); } /* --- a/kernel/rcu/tree.h +++ b/kernel/rcu/tree.h @@ -389,6 +389,10 @@ struct rcu_state { const char *name; /* Name of structure. */ char abbr; /* Abbreviated name. */ struct list_head flavors; /* List of RCU flavors. */ + + spinlock_t ofl_lock ____cacheline_internodealigned_in_smp; + /* Synchronize offline with */ + /* GP pre-initialization. */ }; /* Values for rcu_state structure's gp_flags field. */