Received: by 2002:ac0:a5a6:0:0:0:0:0 with SMTP id m35-v6csp2474607imm; Mon, 24 Sep 2018 05:08:05 -0700 (PDT) X-Google-Smtp-Source: ANB0VdZVU+ddtK5zF5l4Zw+M0Wes2TYST+eHMH+vjpNFIzoW68rR5uukvgdRfPBGhG7NxE7mZ1AJ X-Received: by 2002:a62:3c7:: with SMTP id 190-v6mr10019621pfd.145.1537790885077; Mon, 24 Sep 2018 05:08:05 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1537790885; cv=none; d=google.com; s=arc-20160816; b=sdP5tGJS5t7kjRpbDHfzaV6iQ6LViW5+deITJFdVVXs3Xs7OsUtaU22B/H+OWDHr3M W21DgvgDmqUCPlBO1EoIJ1tvB55+1xhnchkLfLrIFznTMGCLtAh1AhccaM+BIrjZiB27 JB4Ghk1DcZBoAk7MjP3z5u4oJVSSxOS89QsGXyghKGGXsKN5W+m4S69Ap+fddTLuruwM 1uSrPwsUggJKeGHn6VX7VzgOV6TM/4pauWPk38OPYQ0Z9VDOtpIaoan41W3tYroyzfiM wyAmQO573Zz/MlkhZ/AnRNxkC7oTgYH6m7LTHEaeYuZ/82/peWeuV7oH4rF3aDukXHCB Xxmg== 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=qRyAnj/vGDahGCBgPYtqxusLj6jQnAZEElL/Sw/sJ88=; b=ZWAn7g+zKrOtWG9GqYyu5323RitO+ge/O+h9tKIpFXis/FwrLHMg1N0cAG69AJcszg Kb9EHpiYouIW32s5UvtFpXcToTWI4WmqHzxVi4PhNMiV7QW7mo5DIjqimGG3i1v9VImN o2GHoEMDfTeOL+swwdxvDfJthrkub+LtgTT3W/W9WjTYsbUXGPhxzd0YOJXLrS4CrqGS woWJSny+/NZSj1y7Q8oXy+2eHtWnqh1Bt+h9ESOZ0s+yMB7o3urPwXJHGXPIEJjlXFQA P6RW9MCKjo3BpcOz4l7R6oK3Bv7IAROcIIezxKtz/fiuyRK4yZoT0o5/sqBprEm3ktSr OmmQ== 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 y129-v6si11783157pgy.551.2018.09.24.05.07.49; Mon, 24 Sep 2018 05:08:05 -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 S1731193AbeIXSIi (ORCPT + 99 others); Mon, 24 Sep 2018 14:08:38 -0400 Received: from mail.linuxfoundation.org ([140.211.169.12]:54142 "EHLO mail.linuxfoundation.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729023AbeIXSIh (ORCPT ); Mon, 24 Sep 2018 14:08:37 -0400 Received: from localhost (ip-213-127-77-73.ip.prioritytelecom.net [213.127.77.73]) by mail.linuxfoundation.org (Postfix) with ESMTPSA id B8CAD107B; Mon, 24 Sep 2018 12:06:48 +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.9 094/111] rcu: Fix grace-period hangs due to race with CPU offline Date: Mon, 24 Sep 2018 13:53:01 +0200 Message-Id: <20180924113114.247174991@linuxfoundation.org> X-Mailer: git-send-email 2.19.0 In-Reply-To: <20180924113103.337261320@linuxfoundation.org> References: <20180924113103.337261320@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.9-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); @@ -1966,11 +1967,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; } @@ -2005,6 +2008,7 @@ static bool rcu_gp_init(struct rcu_state } raw_spin_unlock_irq_rcu_node(rnp); + spin_unlock(&rsp->ofl_lock); } /* @@ -3915,9 +3919,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); } void rcu_report_dead(unsigned int cpu) --- a/kernel/rcu/tree.h +++ b/kernel/rcu/tree.h @@ -550,6 +550,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. */