Received: by 2002:a05:6a11:4021:0:0:0:0 with SMTP id ky33csp224735pxb; Mon, 13 Sep 2021 17:38:09 -0700 (PDT) X-Google-Smtp-Source: ABdhPJwrAJjNDvyZwrHS7LF4dKKKAQvtE9Fr8wh5GgSN1qti0VnlhUFZUBZKXheK3itwcrFg57/D X-Received: by 2002:a17:906:c252:: with SMTP id bl18mr15387783ejb.519.1631579889286; Mon, 13 Sep 2021 17:38:09 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1631579889; cv=none; d=google.com; s=arc-20160816; b=N1rKwukeTuMAC6yqt0zyJfj53ntitrfgC/7MdC7WNWuRcFQxnjgo2nRgupbpfddRTy aS43rVsVF+99uE7zHbyBfQvpcKpSFw92EsSUaO6XCdffiRdhDkay8z/bx/HAFknyQKJQ BpyLYHdgEVhMcgX9plkqUt+aG5M6gd6KU2XX0kR0TIK6jAwZW6XFKZkIebQEQncnzoUq AHOrsQEQ2NQ+WA1Yhee0qTrUZOPyBMoO3XA5kl0CkQp7PvJbSfTrUCOyR0UkabROCg0N k+6b+ESJc+2sfIPILyKcEcYSWYGdcj5hW9N9HvCcAIvwdbwLTm6zmLzLHAjdrBo4BzRy Z74w== 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=0EEzgGyCO5UZ3cYiFmtPouPFI+ifpvyEa+2lp2uWrTQ=; b=w5bCrj2PFT9jsqSzLqR/Sze+5OCYSzT3t4AE42nhbfYDebY6Bb1niHcT3jjLwq6HOH GH2fB3tAeDtWJlB4u38yfVizMP7gZSXKgf1yOTQFDlZouCzLmTMwvoDep4N+kXRL12gv iPK4TyEGSfk8VUMHpSpyxmdxW/qtjrraxiMKdcTA2w1qyCQ9Uk7rzLpXheF5Gv/QAacv 7LDbpq1zqTx3xPSUZp6XEhJ6A0jf3VTFc+vrYgD5e4ZjDLLxMFEabWY+tYyJLJzK4Csl NoDJTOdLsWvv2o8xecEb4fCowBOlSnb6lzhTa22Ro6rTu5lwdq1fbSDQiV45lWdywUJK j5Iw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=vQN8KgS5; 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 u19si8896535ejo.211.2021.09.13.17.37.45; Mon, 13 Sep 2021 17:38:09 -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=vQN8KgS5; 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 S1348485AbhIMOuj (ORCPT + 99 others); Mon, 13 Sep 2021 10:50:39 -0400 Received: from mail.kernel.org ([198.145.29.99]:60464 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1346227AbhIMOpS (ORCPT ); Mon, 13 Sep 2021 10:45:18 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id 07946619EA; Mon, 13 Sep 2021 13:58:13 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1631541494; bh=PEzcHtqFC7oZw+xmy2y2rPKeywLpKGwnMwJK2w7KoW0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=vQN8KgS5o/kVRuz5oBjxecae4rTzDFRqo4EseToe28dnuW3bYpdCapPx31na0isCu qhRNND7deSq2mWs56tYoad8pPg+985eSrV6vCKNCI1zAk506ap0K99DWWY/slbLIxD O4Y0I5Q/++m3A/k/4IvyL6gBtY+lM+o3gZgmzPu4= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Johannes Lundberg , Jens Axboe Subject: [PATCH 5.14 320/334] io-wq: check max_worker limits if a worker transitions bound state Date: Mon, 13 Sep 2021 15:16:14 +0200 Message-Id: <20210913131124.247988603@linuxfoundation.org> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20210913131113.390368911@linuxfoundation.org> References: <20210913131113.390368911@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 ecc53c48c13d995e6fe5559e30ffee48d92784fd upstream. For the two places where new workers are created, we diligently check if we are allowed to create a new worker. If we're currently at the limit of how many workers of a given type we can have, then we don't create any new ones. If you have a mixed workload with various types of bound and unbounded work, then it can happen that a worker finishes one type of work and is then transitioned to the other type. For this case, we don't check if we are actually allowed to do so. This can cause io-wq to temporarily exceed the allowed number of workers for a given type. When retrieving work, check that the types match. If they don't, check if we are allowed to transition to the other type. If not, then don't handle the new work. Cc: stable@vger.kernel.org Reported-by: Johannes Lundberg Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman --- fs/io-wq.c | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) --- a/fs/io-wq.c +++ b/fs/io-wq.c @@ -423,7 +423,28 @@ static void io_wait_on_hash(struct io_wq spin_unlock(&wq->hash->wait.lock); } -static struct io_wq_work *io_get_next_work(struct io_wqe *wqe) +/* + * We can always run the work if the worker is currently the same type as + * the work (eg both are bound, or both are unbound). If they are not the + * same, only allow it if incrementing the worker count would be allowed. + */ +static bool io_worker_can_run_work(struct io_worker *worker, + struct io_wq_work *work) +{ + struct io_wqe_acct *acct; + + if (!(worker->flags & IO_WORKER_F_BOUND) != + !(work->flags & IO_WQ_WORK_UNBOUND)) + return true; + + /* not the same type, check if we'd go over the limit */ + acct = io_work_get_acct(worker->wqe, work); + return acct->nr_workers < acct->max_workers; +} + +static struct io_wq_work *io_get_next_work(struct io_wqe *wqe, + struct io_worker *worker, + bool *stalled) __must_hold(wqe->lock) { struct io_wq_work_node *node, *prev; @@ -435,6 +456,9 @@ static struct io_wq_work *io_get_next_wo work = container_of(node, struct io_wq_work, list); + if (!io_worker_can_run_work(worker, work)) + break; + /* not hashed, can run anytime */ if (!io_wq_is_hashed(work)) { wq_list_del(&wqe->work_list, node, prev); @@ -461,6 +485,7 @@ static struct io_wq_work *io_get_next_wo raw_spin_unlock(&wqe->lock); io_wait_on_hash(wqe, stall_hash); raw_spin_lock(&wqe->lock); + *stalled = true; } return NULL; @@ -500,6 +525,7 @@ static void io_worker_handle_work(struct do { struct io_wq_work *work; + bool stalled; get_next: /* * If we got some work, mark us as busy. If we didn't, but @@ -508,10 +534,11 @@ get_next: * can't make progress, any work completion or insertion will * clear the stalled flag. */ - work = io_get_next_work(wqe); + stalled = false; + work = io_get_next_work(wqe, worker, &stalled); if (work) __io_worker_busy(wqe, worker, work); - else if (!wq_list_empty(&wqe->work_list)) + else if (stalled) wqe->flags |= IO_WQE_FLAG_STALLED; raw_spin_unlock_irq(&wqe->lock);