Received: by 2002:a25:8b91:0:0:0:0:0 with SMTP id j17csp13959032ybl; Mon, 30 Dec 2019 01:06:19 -0800 (PST) X-Google-Smtp-Source: APXvYqzSbrZ75yQndiPyCRoU0fIECWXyVis8SDkika5WB5SEzwCt3Nf1TlebBQQuYQ/pAgCQ9jxw X-Received: by 2002:a05:6830:1cc9:: with SMTP id p9mr48143581otg.59.1577696779732; Mon, 30 Dec 2019 01:06:19 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1577696779; cv=none; d=google.com; s=arc-20160816; b=t+owKbxqpU5RDi29mboVYqBQo28irsHwkoJYX+5QtOtWnc6T88RyNCF/PSzvpssMao MXX8gx2U65UZSMPjQDPXN2j4uvPjcizQiB/hsA4cypVeEYpEhRiHQ9lHmd+xFVFPXSwb uZAyWBrSZrlSEEQ9NQPKuPZGP9FYfcSM86ndM/RfZpFOVWJAWymhNqy3iUYc642NPl4R 8p8p9TwJMz5VvDUs++XGvq6sW21BHB84z64M6J5OiIw099qpVkH8SmyB1D4g36cz8lwz Z0prBDajL1vNWAF0O8/XPGJ2KUOAPMDpO8tZyJStLv6QfZRIFPZFuVdu2kxKgpeklN6W O3Eg== 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 :references:in-reply-to:message-id:date:subject:cc:to:from; bh=9sM3cUkn4lEJjvkSdRjtxQipR8KrIa2Xf5GnfV+4ce8=; b=LS7Sbh6dAJlygLNZ8Ser+7+3xm9HFb/m6qpTfNPATgkyxYFH/RTkdUFt0kdKrlR8ch O7NqbhEsnpd7UuIgTlr2RqC6oEqxopJsZO+i6ElXTPB5u7V7jvAqTRerEkvXpSuTdKl+ ihqaxrS2UHV6x3UeRxkiXmhf4clrIyKvqA4KOzUR3ILCzXzFOPV0Sv8L1rEeNSM8mFZH 6QW00Xq5a0w8w5DdX6+dXsQLopEyX85He2vqwbcjg9LmfSfwPZuXSV4jFs9AJNgN1nRs ZG3ngR0z2sXo+d5g3GuPjxdzi0753Ihn5VpT0qgVT12d2/4quCC/2oM92+IDM1BNAWnf h14Q== 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 z65si11980375oia.33.2019.12.30.01.06.06; Mon, 30 Dec 2019 01:06:19 -0800 (PST) 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 S1727260AbfL3JFN (ORCPT + 99 others); Mon, 30 Dec 2019 04:05:13 -0500 Received: from mail.fireflyinternet.com ([109.228.58.192]:53206 "EHLO fireflyinternet.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1727175AbfL3JFM (ORCPT ); Mon, 30 Dec 2019 04:05:12 -0500 X-Default-Received-SPF: pass (skip=forwardok (res=PASS)) x-ip-name=78.156.65.138; Received: from haswell.alporthouse.com (unverified [78.156.65.138]) by fireflyinternet.com (Firefly Internet (M1)) with ESMTP id 19724165-1500050 for multiple; Mon, 30 Dec 2019 09:04:46 +0000 From: Chris Wilson To: linux-kernel@vger.kernel.org Cc: Chris Wilson , Frederic Weisbecker , Peter Zijlstra , Ingo Molnar Subject: [PATCH] sched/vtime: Prevent unstable evaluation of WARN(vtime->state) Date: Mon, 30 Dec 2019 09:04:36 +0000 Message-Id: <20191230090436.3749235-1-chris@chris-wilson.co.uk> X-Mailer: git-send-email 2.25.0.rc0 In-Reply-To: <20191230010839.GA8740@lenoir> References: <20191230010839.GA8740@lenoir> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org As the vtime is sampled under loose seqcount protection by kcpustat, the vtime fields may change as the code flows. Where logic dictates a field has a static value, use a READ_ONCE. Fixes: 74722bb223d0 ("sched/vtime: Bring up complete kcpustat accessor") Signed-off-by: Chris Wilson Cc: Frederic Weisbecker Cc: Peter Zijlstra Cc: Ingo Molnar --- kernel/sched/cputime.c | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/kernel/sched/cputime.c b/kernel/sched/cputime.c index d43318a489f2..96bbd52f43ae 100644 --- a/kernel/sched/cputime.c +++ b/kernel/sched/cputime.c @@ -914,6 +914,8 @@ void task_cputime(struct task_struct *t, u64 *utime, u64 *stime) static int vtime_state_check(struct vtime *vtime, int cpu) { + int state = READ_ONCE(vtime->state); + /* * We raced against a context switch, fetch the * kcpustat task again. @@ -930,10 +932,10 @@ static int vtime_state_check(struct vtime *vtime, int cpu) * * Case 1) is ok but 2) is not. So wait for a safe VTIME state. */ - if (vtime->state == VTIME_INACTIVE) + if (state == VTIME_INACTIVE) return -EAGAIN; - return 0; + return state; } static u64 kcpustat_user_vtime(struct vtime *vtime) @@ -952,14 +954,15 @@ static int kcpustat_field_vtime(u64 *cpustat, { struct vtime *vtime = &tsk->vtime; unsigned int seq; - int err; do { + int state; + seq = read_seqcount_begin(&vtime->seqcount); - err = vtime_state_check(vtime, cpu); - if (err < 0) - return err; + state = vtime_state_check(vtime, cpu); + if (state < 0) + return state; *val = cpustat[usage]; @@ -972,7 +975,7 @@ static int kcpustat_field_vtime(u64 *cpustat, */ switch (usage) { case CPUTIME_SYSTEM: - if (vtime->state == VTIME_SYS) + if (state == VTIME_SYS) *val += vtime->stime + vtime_delta(vtime); break; case CPUTIME_USER: @@ -984,11 +987,11 @@ static int kcpustat_field_vtime(u64 *cpustat, *val += kcpustat_user_vtime(vtime); break; case CPUTIME_GUEST: - if (vtime->state == VTIME_GUEST && task_nice(tsk) <= 0) + if (state == VTIME_GUEST && task_nice(tsk) <= 0) *val += vtime->gtime + vtime_delta(vtime); break; case CPUTIME_GUEST_NICE: - if (vtime->state == VTIME_GUEST && task_nice(tsk) > 0) + if (state == VTIME_GUEST && task_nice(tsk) > 0) *val += vtime->gtime + vtime_delta(vtime); break; default: @@ -1039,23 +1042,23 @@ static int kcpustat_cpu_fetch_vtime(struct kernel_cpustat *dst, { struct vtime *vtime = &tsk->vtime; unsigned int seq; - int err; do { u64 *cpustat; u64 delta; + int state; seq = read_seqcount_begin(&vtime->seqcount); - err = vtime_state_check(vtime, cpu); - if (err < 0) - return err; + state = vtime_state_check(vtime, cpu); + if (state < 0) + return state; *dst = *src; cpustat = dst->cpustat; /* Task is sleeping, dead or idle, nothing to add */ - if (vtime->state < VTIME_SYS) + if (state < VTIME_SYS) continue; delta = vtime_delta(vtime); @@ -1064,15 +1067,15 @@ static int kcpustat_cpu_fetch_vtime(struct kernel_cpustat *dst, * Task runs either in user (including guest) or kernel space, * add pending nohz time to the right place. */ - if (vtime->state == VTIME_SYS) { + if (state == VTIME_SYS) { cpustat[CPUTIME_SYSTEM] += vtime->stime + delta; - } else if (vtime->state == VTIME_USER) { + } else if (state == VTIME_USER) { if (task_nice(tsk) > 0) cpustat[CPUTIME_NICE] += vtime->utime + delta; else cpustat[CPUTIME_USER] += vtime->utime + delta; } else { - WARN_ON_ONCE(vtime->state != VTIME_GUEST); + WARN_ON_ONCE(state != VTIME_GUEST); if (task_nice(tsk) > 0) { cpustat[CPUTIME_GUEST_NICE] += vtime->gtime + delta; cpustat[CPUTIME_NICE] += vtime->gtime + delta; @@ -1083,7 +1086,7 @@ static int kcpustat_cpu_fetch_vtime(struct kernel_cpustat *dst, } } while (read_seqcount_retry(&vtime->seqcount, seq)); - return err; + return 0; } void kcpustat_cpu_fetch(struct kernel_cpustat *dst, int cpu) -- 2.25.0.rc0