Received: by 2002:a05:6a11:4021:0:0:0:0 with SMTP id ky33csp1899281pxb; Thu, 16 Sep 2021 19:32:46 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxDWPbMHY110nSZjSI0zVgXlwMF/vt4fLDSt92Bnme7eOFUUPyLTV0VQnjG8sHKX0hSxp/c X-Received: by 2002:a6b:d617:: with SMTP id w23mr6592188ioa.89.1631845966235; Thu, 16 Sep 2021 19:32:46 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1631845966; cv=none; d=google.com; s=arc-20160816; b=zq2aLh5nLi842N//1vhjfRWFuSYVSY4dOyu/QbdwTxWbSHhNQTHoL1iJYbzoGQ32ls aoyzbQhwdygFBmjMIbRCxV0NiK2QMHLurnMmvU7LE3P1/Y5mi8GmxsiGGOjn7IfUd9s/ UK9fgpiJfVOQW+/xDLLF44blHqDraT1P7jhjbM3NeS9y1ltNuNyudbfHy3is9tZV3y/1 cJvuff9THwZxscFn4WYbk2oDgzTHUb1szWMSueKDuTreMi71r69ycqJSEMb+d8qM/Aw0 l+nBEetXs2Iblor5mV35QSzWirHCZt+MDK1bFa5kpKlKz7RLN0k3cmbdQU4Wn+1Qnn4E 8XdQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=lGsJQmxPzCdQ8qrhYcEcxwoWdwBmXoca9bGqYsccBtA=; b=hiKksdTUJnsvf+XTyXjjOU0kRfZH5IsCdc6xPjc2Qe5IiHI3j7j5xdZjVPc4r8TQF/ cC0ExcjXci7OqvXvJMdTIfg49JghSOBELDEV3vt+K8bZdTg3TUO04Sp7sKP9QsFAqWtz /ozGbflYgiQr9n7xQESlYJY1TPGvlvz1tryymi98/Ivek4asyN8q47vsQR/j4LFqWmAK YJoWNcklRI7Y9TvaG7dtbl79yQNf3V2QEL0jVUm5tvXYNtBYd7h9VpalHLxf9SRLLxeb 5NzBr61StMB72I9g54YQaPCzZ9aQ3o+OhObuE/7E/mldXVN55V8DqeK/LmoC5ge3gZiC GzOQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=gEogJYuZ; 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=linuxfoundation.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id d9si4338381ilv.97.2021.09.16.19.32.35; Thu, 16 Sep 2021 19:32:46 -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=@linuxfoundation.org header.s=korg header.b=gEogJYuZ; 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=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1350954AbhIPROX (ORCPT + 99 others); Thu, 16 Sep 2021 13:14:23 -0400 Received: from mail.kernel.org ([198.145.29.99]:35904 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1349454AbhIPRFv (ORCPT ); Thu, 16 Sep 2021 13:05:51 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id 0980B61B2A; Thu, 16 Sep 2021 16:35:22 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1631810123; bh=+s9+JusyiLz4K56XmSRglH6aBHfMJg+bUZjXsuTEQw8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=gEogJYuZ7RvuVImXGgojoa7Jn6hDNiD3/fPpzmN7m96dD36KSyHtEN8rIvx/4eeIe FrtAYEjf7fHq8RayiswiUxwf5m5RTbvKGWrGCW65MaHwS5V49Sw+cifpIj29u/2Vk2 BncifZ1krBDh5mQtXAk1PxLT8sqLiCC+5HtUyZ2k= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Andres Freund , Jens Axboe Subject: [PATCH 5.14 007/432] io-wq: fix race between adding work and activating a free worker Date: Thu, 16 Sep 2021 17:55:56 +0200 Message-Id: <20210916155811.067665251@linuxfoundation.org> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20210916155810.813340753@linuxfoundation.org> References: <20210916155810.813340753@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Jens Axboe commit 94ffb0a282872c2f4b14f757fa1aef2302aeaabb upstream. The attempt to find and activate a free worker for new work is currently combined with creating a new one if we don't find one, but that opens io-wq up to a race where the worker that is found and activated can put itself to sleep without knowing that it has been selected to perform this new work. Fix this by moving the activation into where we add the new work item, then we can retain it within the wqe->lock scope and elimiate the race with the worker itself checking inside the lock, but sleeping outside of it. Cc: stable@vger.kernel.org Reported-by: Andres Freund Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman --- fs/io-wq.c | 50 ++++++++++++++++++++++++-------------------------- 1 file changed, 24 insertions(+), 26 deletions(-) --- a/fs/io-wq.c +++ b/fs/io-wq.c @@ -236,9 +236,9 @@ static bool io_wqe_activate_free_worker( * We need a worker. If we find a free one, we're good. If not, and we're * below the max number of workers, create one. */ -static void io_wqe_wake_worker(struct io_wqe *wqe, struct io_wqe_acct *acct) +static void io_wqe_create_worker(struct io_wqe *wqe, struct io_wqe_acct *acct) { - bool ret; + bool do_create = false, first = false; /* * Most likely an attempt to queue unbounded work on an io_wq that @@ -247,25 +247,18 @@ static void io_wqe_wake_worker(struct io if (unlikely(!acct->max_workers)) pr_warn_once("io-wq is not configured for unbound workers"); - rcu_read_lock(); - ret = io_wqe_activate_free_worker(wqe); - rcu_read_unlock(); - - if (!ret) { - bool do_create = false, first = false; - - raw_spin_lock_irq(&wqe->lock); - if (acct->nr_workers < acct->max_workers) { - atomic_inc(&acct->nr_running); - atomic_inc(&wqe->wq->worker_refs); - if (!acct->nr_workers) - first = true; - acct->nr_workers++; - do_create = true; - } - raw_spin_unlock_irq(&wqe->lock); - if (do_create) - create_io_worker(wqe->wq, wqe, acct->index, first); + raw_spin_lock_irq(&wqe->lock); + if (acct->nr_workers < acct->max_workers) { + if (!acct->nr_workers) + first = true; + acct->nr_workers++; + do_create = true; + } + raw_spin_unlock_irq(&wqe->lock); + if (do_create) { + atomic_inc(&acct->nr_running); + atomic_inc(&wqe->wq->worker_refs); + create_io_worker(wqe->wq, wqe, acct->index, first); } } @@ -793,7 +786,8 @@ append: static void io_wqe_enqueue(struct io_wqe *wqe, struct io_wq_work *work) { struct io_wqe_acct *acct = io_work_get_acct(wqe, work); - bool do_wake; + unsigned work_flags = work->flags; + bool do_create; unsigned long flags; /* @@ -809,12 +803,16 @@ static void io_wqe_enqueue(struct io_wqe raw_spin_lock_irqsave(&wqe->lock, flags); io_wqe_insert_work(wqe, work); wqe->flags &= ~IO_WQE_FLAG_STALLED; - do_wake = (work->flags & IO_WQ_WORK_CONCURRENT) || - !atomic_read(&acct->nr_running); + + rcu_read_lock(); + do_create = !io_wqe_activate_free_worker(wqe); + rcu_read_unlock(); + raw_spin_unlock_irqrestore(&wqe->lock, flags); - if (do_wake) - io_wqe_wake_worker(wqe, acct); + if (do_create && ((work_flags & IO_WQ_WORK_CONCURRENT) || + !atomic_read(&acct->nr_running))) + io_wqe_create_worker(wqe, acct); } void io_wq_enqueue(struct io_wq *wq, struct io_wq_work *work)