Received: by 2002:a05:6a10:1287:0:0:0:0 with SMTP id d7csp648400pxv; Thu, 15 Jul 2021 12:25:24 -0700 (PDT) X-Google-Smtp-Source: ABdhPJyqSvLpvre8rSEwLAB5ExNHxp1qxsPAhCgotHWVAcH9LfHsRgj3CMoU54aufV2fk759IAom X-Received: by 2002:a17:906:a450:: with SMTP id cb16mr3001629ejb.296.1626377124680; Thu, 15 Jul 2021 12:25:24 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1626377124; cv=none; d=google.com; s=arc-20160816; b=M/O3inPazQmEJsnJrw8HxLiN4dsHV8miA2ZyEcRqEg7XScjSv2uRNNkvvWHAj7KM2l zmKx0Jq6jz/9/CZicrd1G3mWAWzLWZYdQJ4KV10fWephAXp0KxORhUQ/kpsQz6l1jBYv Pg2JV0n7MUP8p6O1dRekZt6ZO/kvYrHGX2wqpSoB5iZG8ZmZvnS7htTgtXWQN3Aq0t3+ f1ugRpjBOn3l004WomfTK4BJ2cZhmN2jd9Sy7+2OwEHfeib6pvDwa+QCeJciSY7MHU6w +qBB4Khrpn7KtG1sdtEz9ypMyOVQ//88okP7C/MKYYzjMY81PTkTlXlj4TKRVoD7ZW+A vsTg== 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=eurbFb/f9aGJRAX0Dup8Zf1DmXmnjNLO1qgEYrjtJ7Q=; b=WcnZxWnApwrJtfKSwRwaEy3xSlTtow7zTcNy99YEMI8IRhdfGmeszJ8SEqyE5O2Ekh isVqetdn0e6i6hRfIMABFH95UjVWwMA+FxYscqiA7IfMMlmWxGHg/AQ/VGm7oZlgORiI 7WtgGng3lpSJ8ltR8WPo4JoAqvl3EM+DefrdT5Yf8Ynk7ULbk9OIhBlXpmVXP+r9qjFs NQI60FWWJA5dTtqD4upP2B2utFMqRgRGlqHSsjy+PM8MEgKce+U7iyVvKa2YQJ/ZGQOl gyTlcAbsAN/dxGyv+sM5bO/qx7ICM/IEy3dW/CN5Jx1KutcpDnN4s4oZyr9uL1T9aMVj 0K3A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=Rm6IqwFp; 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 5si8444503ejn.172.2021.07.15.12.25.01; Thu, 15 Jul 2021 12:25:24 -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=Rm6IqwFp; 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 S1343524AbhGOTY1 (ORCPT + 99 others); Thu, 15 Jul 2021 15:24:27 -0400 Received: from mail.kernel.org ([198.145.29.99]:46114 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S240979AbhGOTHj (ORCPT ); Thu, 15 Jul 2021 15:07:39 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id 91321613C0; Thu, 15 Jul 2021 19:03:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1626375811; bh=a8HQpoma7Ibv4xF/ZTkzqoEoiGyezdcXHCykpae5DIw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Rm6IqwFp5eCTl7KJUd+47wf5GsEQkFp62GmyK9R8Pjj08KYhJJWOywyxqSSvJd5o1 2hJgfM+MdHftGNaFgqfxhtaAXIdB/YRyzoS6XuXSqj7cmNJtS6zQ9swJGwe1m8lAMo s6c/gORW8JN2aDNiHmiMNBosGvwjnELCz3a744P0= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Jan Kara , Jens Axboe Subject: [PATCH 5.12 209/242] rq-qos: fix missed wake-ups in rq_qos_throttle try two Date: Thu, 15 Jul 2021 20:39:31 +0200 Message-Id: <20210715182630.050001104@linuxfoundation.org> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210715182551.731989182@linuxfoundation.org> References: <20210715182551.731989182@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: Jan Kara commit 11c7aa0ddea8611007768d3e6b58d45dc60a19e1 upstream. Commit 545fbd0775ba ("rq-qos: fix missed wake-ups in rq_qos_throttle") tried to fix a problem that a process could be sleeping in rq_qos_wait() without anyone to wake it up. However the fix is not complete and the following can still happen: CPU1 (waiter1) CPU2 (waiter2) CPU3 (waker) rq_qos_wait() rq_qos_wait() acquire_inflight_cb() -> fails acquire_inflight_cb() -> fails completes IOs, inflight decreased prepare_to_wait_exclusive() prepare_to_wait_exclusive() has_sleeper = !wq_has_single_sleeper() -> true as there are two sleepers has_sleeper = !wq_has_single_sleeper() -> true io_schedule() io_schedule() Deadlock as now there's nobody to wakeup the two waiters. The logic automatically blocking when there are already sleepers is really subtle and the only way to make it work reliably is that we check whether there are some waiters in the queue when adding ourselves there. That way, we are guaranteed that at least the first process to enter the wait queue will recheck the waiting condition before going to sleep and thus guarantee forward progress. Fixes: 545fbd0775ba ("rq-qos: fix missed wake-ups in rq_qos_throttle") CC: stable@vger.kernel.org Signed-off-by: Jan Kara Link: https://lore.kernel.org/r/20210607112613.25344-1-jack@suse.cz Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman --- block/blk-rq-qos.c | 4 ++-- include/linux/wait.h | 2 +- kernel/sched/wait.c | 9 +++++++-- 3 files changed, 10 insertions(+), 5 deletions(-) --- a/block/blk-rq-qos.c +++ b/block/blk-rq-qos.c @@ -266,8 +266,8 @@ void rq_qos_wait(struct rq_wait *rqw, vo if (!has_sleeper && acquire_inflight_cb(rqw, private_data)) return; - prepare_to_wait_exclusive(&rqw->wait, &data.wq, TASK_UNINTERRUPTIBLE); - has_sleeper = !wq_has_single_sleeper(&rqw->wait); + has_sleeper = !prepare_to_wait_exclusive(&rqw->wait, &data.wq, + TASK_UNINTERRUPTIBLE); do { /* The memory barrier in set_task_state saves us here. */ if (data.got_token) --- a/include/linux/wait.h +++ b/include/linux/wait.h @@ -1136,7 +1136,7 @@ do { \ * Waitqueues which are removed from the waitqueue_head at wakeup time */ void prepare_to_wait(struct wait_queue_head *wq_head, struct wait_queue_entry *wq_entry, int state); -void prepare_to_wait_exclusive(struct wait_queue_head *wq_head, struct wait_queue_entry *wq_entry, int state); +bool prepare_to_wait_exclusive(struct wait_queue_head *wq_head, struct wait_queue_entry *wq_entry, int state); long prepare_to_wait_event(struct wait_queue_head *wq_head, struct wait_queue_entry *wq_entry, int state); void finish_wait(struct wait_queue_head *wq_head, struct wait_queue_entry *wq_entry); long wait_woken(struct wait_queue_entry *wq_entry, unsigned mode, long timeout); --- a/kernel/sched/wait.c +++ b/kernel/sched/wait.c @@ -264,17 +264,22 @@ prepare_to_wait(struct wait_queue_head * } EXPORT_SYMBOL(prepare_to_wait); -void +/* Returns true if we are the first waiter in the queue, false otherwise. */ +bool prepare_to_wait_exclusive(struct wait_queue_head *wq_head, struct wait_queue_entry *wq_entry, int state) { unsigned long flags; + bool was_empty = false; wq_entry->flags |= WQ_FLAG_EXCLUSIVE; spin_lock_irqsave(&wq_head->lock, flags); - if (list_empty(&wq_entry->entry)) + if (list_empty(&wq_entry->entry)) { + was_empty = list_empty(&wq_head->head); __add_wait_queue_entry_tail(wq_head, wq_entry); + } set_current_state(state); spin_unlock_irqrestore(&wq_head->lock, flags); + return was_empty; } EXPORT_SYMBOL(prepare_to_wait_exclusive);