Received: by 2002:a25:1985:0:0:0:0:0 with SMTP id 127csp2234077ybz; Thu, 23 Apr 2020 14:09:05 -0700 (PDT) X-Google-Smtp-Source: APiQypIeyeNgR475dYT64NdtqMvIwBBtRLIZabeixXBBHodaAj9RDv0/g22ZJvFAY/OB/6LtCSrX X-Received: by 2002:a05:6402:7d6:: with SMTP id u22mr4452388edy.149.1587676145601; Thu, 23 Apr 2020 14:09:05 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1587676145; cv=none; d=google.com; s=arc-20160816; b=piMeOYF4vtZA73r6eQTd6mxVdT5k+qjYXRV+nSZwjan+55kpEB61s3dqfdxAuL7+xh mq35K94cuo2qWQMl3RrcK+6dPdTJ9HswLCNp5yp3F/l5QWv0yHya+lDsp2s32sy/XIjt 1ET0B9xvFdsvaFZE20Se8VQuBKqpWEsUbEXxWUgsYQaakzYF+uOcGhBcgb55pBn/pcMW 8rkdCd4kbqRsQel9C2CeasSfi+gCOE2VjCBXSIWZALdrJRz1QGUsvPyZzKInghd4+IaK Jge6PxQ9Tq6EqrKR80R3Q6XLTtwXeWPFD3Xmv0lKbZocO+2fidAwxZu8jRXEs3oInEbe gclw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:cc:to:from:subject:mime-version :message-id:date:dkim-signature; bh=yS4CittGbOhF42R8TWWDdhwDXYai0/leJlv4gqT/NmU=; b=0BVo3YQmzRfhFqYqDLyCWBgugffCo7fbGiYNc+utI/sWVgGT4Odsyd0VlHvkhpkLNe p0OlKpZQLw4wTgkCLnngY0Ynp9ECVCFM8JUkpY6eyiYIoYnWRfeY1TWv6tpVDkEUOUWi riKUJCxTj3E/GEyvg+Qtg50z4yJtX3DTicW1iLszPF3iScZi8h/qXvWAdJMpwR0eSBE6 C7R955tgYKv14f+wDIoxBYAzia4yvAjBiR5DZ+gVrk+7kIW1wsISOkF7KwmVJPt3lZ0O TYRU40bUFAWCMijjtgQp3Vm1CfFmzPSw4tRPgFbRh17Fvcn86A8IJqlC3Jq4S/Bgk6AJ kjYQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20161025 header.b=MjMAt3Q+; 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=REJECT sp=REJECT dis=NONE) header.from=google.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id cw2si1975775ejb.322.2020.04.23.14.08.41; Thu, 23 Apr 2020 14:09:05 -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=@google.com header.s=20161025 header.b=MjMAt3Q+; 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=REJECT sp=REJECT dis=NONE) header.from=google.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726550AbgDWVGb (ORCPT + 99 others); Thu, 23 Apr 2020 17:06:31 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49644 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725877AbgDWVGa (ORCPT ); Thu, 23 Apr 2020 17:06:30 -0400 Received: from mail-pl1-x64a.google.com (mail-pl1-x64a.google.com [IPv6:2607:f8b0:4864:20::64a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6903AC09B043 for ; Thu, 23 Apr 2020 14:06:29 -0700 (PDT) Received: by mail-pl1-x64a.google.com with SMTP id w7so5797758ply.0 for ; Thu, 23 Apr 2020 14:06:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:message-id:mime-version:subject:from:to:cc; bh=yS4CittGbOhF42R8TWWDdhwDXYai0/leJlv4gqT/NmU=; b=MjMAt3Q+mlUPCn3Q31RVo9VFUEZSn/fgCsj2+47u/QF2NPz4QbAe/vq4BuaTBVgsaW Ald4CFbyRy+x7ubqf4RwZVLcYYeL9DqaoDJ4buPw+2FLaOg6PLBmWUwJ33KYAkBB6iLs vrBWVcAmzLHI5AsoiHSQcFHPf0aQaHBf94lKu9Ot+btIm/j1xgONPA9lDUGGM8mzJ0sM Jr9Qum+CkfMwOw/OeL3WY/01JZ11dC/ncINYa2KAWzo1XcjrXnedfMuYvyeBTmbD+MIg THl5MVODRKtpY856nLQIgy8RMRyfpaUfo5leFwSIFzg8ZVZRmvRfTQDOZv9YmxvBmyAH UpTw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:message-id:mime-version:subject:from:to:cc; bh=yS4CittGbOhF42R8TWWDdhwDXYai0/leJlv4gqT/NmU=; b=YTCkqDVxcT3hHxjfxWSzmBD2RvJEy2qc2OslvPlvWoLH2shCqmcKy5AuaHYlFJi0WX vnVba7Pd5WQQRgvzDhxwU30Qujp+7JwEQ/XT0vAJEnBfp68Jo7minJorez2cGcKifZUL mNxuQZ3Ll2FUfvWAr/+KCqVLuErlp50Hz+0PBNALKnlPaGAyKBIRwu6gFnTT1lMMbvQq 3sAl2C+IDRlvT3pDk8Lt99eh04rbGlgH2C0XDnafH78R78O84we6rCzaPk0XvQyfESEK EIGFNk2HOAJtaMPHqNhX5r/Rp1GDOcOLpbY3uoTmylOUYw+S3sHcvGlSpy/B2DKSXln0 7sGw== X-Gm-Message-State: AGi0PuaM88WmhoHWSIYioThZeeVutfmQ6NJeg8WA1gtu9obuvVmprVHX wvm8maialCp4+bWsx9I3mDzIQ0C8dg== X-Received: by 2002:a63:e708:: with SMTP id b8mr5914784pgi.128.1587675988521; Thu, 23 Apr 2020 14:06:28 -0700 (PDT) Date: Thu, 23 Apr 2020 14:05:23 -0700 Message-Id: <20200423210523.52833-1-sqazi@google.com> Mime-Version: 1.0 X-Mailer: git-send-email 2.26.2.303.gf8c07b1a785-goog Subject: [PATCH v2] block: Limit number of items taken from the I/O scheduler in one go From: Salman Qazi To: Jens Axboe , Ming Lei , Bart Van Assche , linux-block@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Jesse Barnes , Gwendal Grignou , Hannes Reinecke , Christoph Hellwig , Salman Qazi Content-Type: text/plain; charset="UTF-8" Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Flushes bypass the I/O scheduler and get added to hctx->dispatch in blk_mq_sched_bypass_insert. This can happen while a kworker is running hctx->run_work work item and is past the point in blk_mq_sched_dispatch_requests where hctx->dispatch is checked. The blk_mq_do_dispatch_sched call is not guaranteed to end in bounded time, because the I/O scheduler can feed an arbitrary number of commands. Since we have only one hctx->run_work, the commands waiting in hctx->dispatch will wait an arbitrary length of time for run_work to be rerun. A similar phenomenon exists with dispatches from the software queue. The solution is to poll hctx->dispatch in blk_mq_do_dispatch_sched and blk_mq_do_dispatch_ctx and return from the run_work handler and let it rerun. Signed-off-by: Salman Qazi Reviewed-by: Ming Lei --- block/blk-mq-sched.c | 49 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 43 insertions(+), 6 deletions(-) diff --git a/block/blk-mq-sched.c b/block/blk-mq-sched.c index 74cedea56034..b69b780351c1 100644 --- a/block/blk-mq-sched.c +++ b/block/blk-mq-sched.c @@ -84,12 +84,17 @@ void blk_mq_sched_restart(struct blk_mq_hw_ctx *hctx) * Only SCSI implements .get_budget and .put_budget, and SCSI restarts * its queue by itself in its completion handler, so we don't need to * restart queue if .get_budget() returns BLK_STS_NO_RESOURCE. + * + * Returns true if hctx->dispatch was found non-empty and + * run_work has to be run again. This is necessary to avoid + * starving flushes. */ -static void blk_mq_do_dispatch_sched(struct blk_mq_hw_ctx *hctx) +static bool blk_mq_do_dispatch_sched(struct blk_mq_hw_ctx *hctx) { struct request_queue *q = hctx->queue; struct elevator_queue *e = q->elevator; LIST_HEAD(rq_list); + bool ret = false; do { struct request *rq; @@ -97,6 +102,11 @@ static void blk_mq_do_dispatch_sched(struct blk_mq_hw_ctx *hctx) if (e->type->ops.has_work && !e->type->ops.has_work(hctx)) break; + if (!list_empty_careful(&hctx->dispatch)) { + ret = true; + break; + } + if (!blk_mq_get_dispatch_budget(hctx)) break; @@ -113,6 +123,8 @@ static void blk_mq_do_dispatch_sched(struct blk_mq_hw_ctx *hctx) */ list_add(&rq->queuelist, &rq_list); } while (blk_mq_dispatch_rq_list(q, &rq_list, true)); + + return ret; } static struct blk_mq_ctx *blk_mq_next_ctx(struct blk_mq_hw_ctx *hctx, @@ -130,16 +142,26 @@ static struct blk_mq_ctx *blk_mq_next_ctx(struct blk_mq_hw_ctx *hctx, * Only SCSI implements .get_budget and .put_budget, and SCSI restarts * its queue by itself in its completion handler, so we don't need to * restart queue if .get_budget() returns BLK_STS_NO_RESOURCE. + * + * Returns true if hctx->dispatch was found non-empty and + * run_work has to be run again. This is necessary to avoid + * starving flushes. */ -static void blk_mq_do_dispatch_ctx(struct blk_mq_hw_ctx *hctx) +static bool blk_mq_do_dispatch_ctx(struct blk_mq_hw_ctx *hctx) { struct request_queue *q = hctx->queue; LIST_HEAD(rq_list); struct blk_mq_ctx *ctx = READ_ONCE(hctx->dispatch_from); + bool ret = false; do { struct request *rq; + if (!list_empty_careful(&hctx->dispatch)) { + ret = true; + break; + } + if (!sbitmap_any_bit_set(&hctx->ctx_map)) break; @@ -165,6 +187,7 @@ static void blk_mq_do_dispatch_ctx(struct blk_mq_hw_ctx *hctx) } while (blk_mq_dispatch_rq_list(q, &rq_list, true)); WRITE_ONCE(hctx->dispatch_from, ctx); + return ret; } void blk_mq_sched_dispatch_requests(struct blk_mq_hw_ctx *hctx) @@ -172,6 +195,8 @@ void blk_mq_sched_dispatch_requests(struct blk_mq_hw_ctx *hctx) struct request_queue *q = hctx->queue; struct elevator_queue *e = q->elevator; const bool has_sched_dispatch = e && e->type->ops.dispatch_request; + bool run_again; + bool restarted = false; LIST_HEAD(rq_list); /* RCU or SRCU read lock is needed before checking quiesced flag */ @@ -180,6 +205,9 @@ void blk_mq_sched_dispatch_requests(struct blk_mq_hw_ctx *hctx) hctx->run++; +again: + run_again = false; + /* * If we have previous entries on our dispatch list, grab them first for * more fair dispatch. @@ -208,19 +236,28 @@ void blk_mq_sched_dispatch_requests(struct blk_mq_hw_ctx *hctx) blk_mq_sched_mark_restart_hctx(hctx); if (blk_mq_dispatch_rq_list(q, &rq_list, false)) { if (has_sched_dispatch) - blk_mq_do_dispatch_sched(hctx); + run_again = blk_mq_do_dispatch_sched(hctx); else - blk_mq_do_dispatch_ctx(hctx); + run_again = blk_mq_do_dispatch_ctx(hctx); } } else if (has_sched_dispatch) { - blk_mq_do_dispatch_sched(hctx); + run_again = blk_mq_do_dispatch_sched(hctx); } else if (hctx->dispatch_busy) { /* dequeue request one by one from sw queue if queue is busy */ - blk_mq_do_dispatch_ctx(hctx); + run_again = blk_mq_do_dispatch_ctx(hctx); } else { blk_mq_flush_busy_ctxs(hctx, &rq_list); blk_mq_dispatch_rq_list(q, &rq_list, false); } + + if (run_again) { + if (!restarted) { + restarted = true; + goto again; + } + + blk_mq_run_hw_queue(hctx, true); + } } bool blk_mq_sched_try_merge(struct request_queue *q, struct bio *bio, -- 2.26.1.301.g55bc3eb7cb9-goog