Received: by 2002:a25:4158:0:0:0:0:0 with SMTP id o85csp5175182yba; Mon, 13 May 2019 06:40:10 -0700 (PDT) X-Google-Smtp-Source: APXvYqwea5rNmkK/VKuYdeOmua4vLltXlbljJ4NglmjzzFde2bd4HvGjAa21e5756oWltQdlqds1 X-Received: by 2002:a65:478a:: with SMTP id e10mr31183952pgs.310.1557754810121; Mon, 13 May 2019 06:40:10 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1557754810; cv=none; d=google.com; s=arc-20160816; b=0xAZe9VeL8YcHqNF7gmmfgyFzsj+yC+zEu3FFxjM5HawJ0JVQG03+BWlihclh+uMG9 M7JVAn5TqPnBHBD03psC0K3CmtlGkPsitLrrEZ7b3q86gOuZRwRWip628t4Dj/mMmt7w ntgJxRz/Uq+du1WVgo3ai1gGRjKNncXNc59dIZzBPwhWmBsCr2sUww/F4huvZr2hu0i0 N+h+q4w+SznWZh9KB95zvcV8J/SLAbwSfG/YWtSoOYmSpyVExnyKYoktfSIoxi6kah1g dQrZNzly4usfh30NX60hs6YZS2Ouho8RELUJwLs0mWLKizRLyGhysqbZ8n4HWHoNtrWP TmKQ== 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 :content-language:in-reply-to:mime-version:user-agent:date :message-id:from:references:cc:to:subject; bh=TwvvW2HiJU9riYo6B9HWmukZwDU+Y5dTef45ACD8VFg=; b=Ep1zYDEtrkUmgqvrrLFDwevMz0FXJWNgWRir5soRs3gRUPnBcFXywA2GhXhSDRP2PP T1HxfPdXA0JCU+ifkP5YF9ctzuZYcvn+iHZioq2rZpltyPzeVYfWSYaXD9/bO01z6SJQ CHPGF0bcxjKkEnugRknwdq/iZXSJM1vXugKchPbmRkuieOiBsJjNoRAEFC481yLp9LXb pPG7K+gZ79VFAKWEAjF2TAkhaRrGl1E4HexFLvjfnyhaP+yoIaj6BpXRxuFqOz4A4CTZ T8jlbD3IGQRWrfZTZ42IeTJnIBDxZ5JtQexXNGFfX3ilYRI2EBHLFKuE4XUwo2jytlmE p6Lg== 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; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=monom.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id l34si16143253pgb.574.2019.05.13.06.39.54; Mon, 13 May 2019 06:40:10 -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; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=monom.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729687AbfEMMNH (ORCPT + 99 others); Mon, 13 May 2019 08:13:07 -0400 Received: from mail.monom.org ([188.138.9.77]:37206 "EHLO mail.monom.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727830AbfEMMNG (ORCPT ); Mon, 13 May 2019 08:13:06 -0400 Received: from mail.monom.org (localhost [127.0.0.1]) by filter.mynetwork.local (Postfix) with ESMTP id A302750065D; Mon, 13 May 2019 14:13:03 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on mail.monom.org X-Spam-Level: X-Spam-Status: No, score=-2.5 required=5.0 tests=ALL_TRUSTED,BAYES_00 autolearn=ham autolearn_force=no version=3.4.2 Received: from [127.0.0.1] (mail.monom.org [188.138.9.77]) by mail.monom.org (Postfix) with ESMTPSA id 42DF75003CD; Mon, 13 May 2019 14:13:03 +0200 (CEST) Subject: Re: [PATCH] Fix a lockup in wait_for_completion() and friends To: minyard@acm.org, linux-rt-users Cc: Corey Minyard , LKML , Peter Zijlstra References: <20190508202759.13842-1-minyard@acm.org> From: Daniel Wagner Message-ID: Date: Mon, 13 May 2019 14:13:02 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.6.1 MIME-Version: 1.0 In-Reply-To: <20190508202759.13842-1-minyard@acm.org> Content-Type: text/plain; charset=utf-8 Content-Language: en-US Content-Transfer-Encoding: 7bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Hi Corey, On 08.05.19 22:27, minyard@acm.org wrote: > From: Corey Minyard > > The function call do_wait_for_common() has a race condition that > can result in lockups waiting for completions. Adding the thread > to (and removing the thread from) the wait queue for the completion > is done outside the do loop in that function. However, if the thread > is woken up with swake_up_locked(), that function will delete the > entry from the wait queue. If that happens and another thread sneaks > in and decrements the done count in the completion to zero, the > loop will go around again, but the thread will no longer be in the > wait queue, so there is no way to wake it up. > > Fix it by adding/removing the thread to/from the wait queue inside > the do loop. > > Fixes: a04ff6b4ec4ee7e ("completion: Use simple wait queues") > Signed-off-by: Corey Minyard Added Peter and lkml to the CC since this is mainline and not -rt only. Thanks, Daniel > --- > This looks like a fairly serious bug, I guess, but I've never seen a > report on it before. > > I found it because I have an out-of-tree feature (hopefully in tree some > day) that takes a core dump of a running process without killing it. It > makes extensive use of completions, and the test code is fairly brutal. > It didn't lock up on stock 4.19, but failed with the RT patches applied. > > The funny thing is, I've never seen this test code fail before on earlier > releases, but it locks up pretty reliably on 4.19-rt. It looks like this > bug goes back to at least the 4.4-rt kernel. But we haven't received any > customer reports of failures. > > The feature and test are in a public tree if someone wants to try to > reproduce this. But hopefully this is pretty obvious with the explaination. > > Also, you could put the DECLARE_SWAITQUEUE() outside the loop, I think, > but maybe it's cleaner or safer to declare it in the loop? If someone > cares I can test it that way. > > -corey > > kernel/sched/completion.c | 8 ++++---- > 1 file changed, 4 insertions(+), 4 deletions(-) > > diff --git a/kernel/sched/completion.c b/kernel/sched/completion.c > index 755a58084978..4cde33cf8b28 100644 > --- a/kernel/sched/completion.c > +++ b/kernel/sched/completion.c > @@ -70,10 +70,10 @@ do_wait_for_common(struct completion *x, > long (*action)(long), long timeout, int state) > { > if (!x->done) { > - DECLARE_SWAITQUEUE(wait); > - > - __prepare_to_swait(&x->wait, &wait); > do { > + DECLARE_SWAITQUEUE(wait); > + > + __prepare_to_swait(&x->wait, &wait); > if (signal_pending_state(state, current)) { > timeout = -ERESTARTSYS; > break; > @@ -82,8 +82,8 @@ do_wait_for_common(struct completion *x, > raw_spin_unlock_irq(&x->wait.lock); > timeout = action(timeout); > raw_spin_lock_irq(&x->wait.lock); > + __finish_swait(&x->wait, &wait); > } while (!x->done && timeout); > - __finish_swait(&x->wait, &wait); > if (!x->done) > return timeout; > } >