From patchwork Thu Sep 13 12:15:39 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ming Lei X-Patchwork-Id: 10599383 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 31BEC14F9 for ; Thu, 13 Sep 2018 12:16:50 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 20B662AABC for ; Thu, 13 Sep 2018 12:16:50 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 151882AAC2; Thu, 13 Sep 2018 12:16:50 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 701182AABC for ; Thu, 13 Sep 2018 12:16:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727473AbeIMR0B (ORCPT ); Thu, 13 Sep 2018 13:26:01 -0400 Received: from mx1.redhat.com ([209.132.183.28]:59700 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727300AbeIMR0B (ORCPT ); Thu, 13 Sep 2018 13:26:01 -0400 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 162DC2C9725; Thu, 13 Sep 2018 12:16:48 +0000 (UTC) Received: from localhost (ovpn-8-34.pek2.redhat.com [10.72.8.34]) by smtp.corp.redhat.com (Postfix) with ESMTP id 1CEFE60BE0; Thu, 13 Sep 2018 12:16:44 +0000 (UTC) From: Ming Lei To: Jens Axboe Cc: linux-block@vger.kernel.org, Ming Lei , Alan Stern , Christoph Hellwig , Bart Van Assche , Jianchao Wang , Hannes Reinecke , Johannes Thumshirn , Adrian Hunter , "James E.J. Bottomley" , "Martin K. Petersen" , linux-scsi@vger.kernel.org Subject: [PATCH V3 10/17] SCSI: deal with admin queue busy Date: Thu, 13 Sep 2018 20:15:39 +0800 Message-Id: <20180913121546.5710-11-ming.lei@redhat.com> In-Reply-To: <20180913121546.5710-1-ming.lei@redhat.com> References: <20180913121546.5710-1-ming.lei@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.29]); Thu, 13 Sep 2018 12:16:48 +0000 (UTC) Sender: linux-scsi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP When request originated from admin queue isn't queued successfully, we deal with it just like for normal requests, that said the admin queue will be rerun after one request in this host is completed. Cc: Alan Stern Cc: Christoph Hellwig Cc: Bart Van Assche Cc: Jianchao Wang Cc: Hannes Reinecke Cc: Johannes Thumshirn Cc: Adrian Hunter Cc: "James E.J. Bottomley" Cc: "Martin K. Petersen" Cc: linux-scsi@vger.kernel.org Signed-off-by: Ming Lei --- drivers/scsi/scsi_lib.c | 61 ++++++++++++++++++++++++++++++++++-------------- include/scsi/scsi_host.h | 2 ++ 2 files changed, 46 insertions(+), 17 deletions(-) diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 1072b2e303d9..8d129b601cc5 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -475,10 +475,14 @@ static void scsi_starved_list_run(struct Scsi_Host *shost) LIST_HEAD(starved_list); struct scsi_device *sdev; unsigned long flags; + bool run_admin; spin_lock_irqsave(shost->host_lock, flags); list_splice_init(&shost->starved_list, &starved_list); + run_admin = shost->run_admin_queue; + shost->run_admin_queue = false; + while (!list_empty(&starved_list)) { struct request_queue *slq; @@ -527,6 +531,10 @@ static void scsi_starved_list_run(struct Scsi_Host *shost) /* put any unprocessed entries back */ list_splice(&starved_list, &shost->starved_list); spin_unlock_irqrestore(shost->host_lock, flags); + + /* no need to get queue for admin_q */ + if (run_admin) + scsi_kick_queue(shost->admin_q); } /* @@ -534,26 +542,30 @@ static void scsi_starved_list_run(struct Scsi_Host *shost) * * Purpose: Select a proper request queue to serve next * - * Arguments: q - last request's queue + * Arguments: sdev - the last request's scsi_device + * q - last request's queue, which may points to + * host->admin_q * * Returns: Nothing * * Notes: The previous command was completely finished, start * a new one if possible. */ -static void scsi_run_queue(struct request_queue *q) +static void scsi_run_queue(struct scsi_device *sdev, struct request_queue *q) { - struct scsi_device *sdev = q->queuedata; + struct Scsi_Host *shost = sdev->host; if (scsi_target(sdev)->single_lun) scsi_single_lun_run(sdev); - if (!list_empty(&sdev->host->starved_list)) - scsi_starved_list_run(sdev->host); - if (q->mq_ops) - blk_mq_run_hw_queues(q, false); - else - blk_run_queue(q); + if (!list_empty(&shost->starved_list) || shost->run_admin_queue) + scsi_starved_list_run(shost); + + scsi_kick_queue(q); + + /* q may points to host->admin_queue */ + if (sdev->request_queue != q) + scsi_kick_queue(sdev->request_queue); } void scsi_requeue_run_queue(struct work_struct *work) @@ -563,7 +575,7 @@ void scsi_requeue_run_queue(struct work_struct *work) sdev = container_of(work, struct scsi_device, requeue_work); q = sdev->request_queue; - scsi_run_queue(q); + scsi_run_queue(sdev, q); } /* @@ -597,7 +609,7 @@ static void scsi_requeue_command(struct request_queue *q, struct scsi_cmnd *cmd) blk_requeue_request(q, req); spin_unlock_irqrestore(q->queue_lock, flags); - scsi_run_queue(q); + scsi_run_queue(sdev, q); put_device(&sdev->sdev_gendev); } @@ -607,7 +619,7 @@ void scsi_run_host_queues(struct Scsi_Host *shost) struct scsi_device *sdev; shost_for_each_device(sdev, shost) - scsi_run_queue(sdev->request_queue); + scsi_run_queue(sdev, sdev->request_queue); } static void scsi_uninit_cmd(struct scsi_cmnd *cmd) @@ -715,8 +727,13 @@ static bool scsi_end_request(struct request *req, blk_status_t error, __blk_mq_end_request(req, error); + /* + * scsi_device is shared between host->admin_queue and + * sdev->request_queue + */ if (scsi_target(sdev)->single_lun || - !list_empty(&sdev->host->starved_list)) + !list_empty(&sdev->host->starved_list) || + sdev->host->run_admin_queue || scsi_is_admin_queue(q)) kblockd_schedule_work(&sdev->requeue_work); else blk_mq_run_hw_queues(q, true); @@ -732,7 +749,7 @@ static bool scsi_end_request(struct request *req, blk_status_t error, blk_finish_request(req, error); spin_unlock_irqrestore(q->queue_lock, flags); - scsi_run_queue(q); + scsi_run_queue(sdev, q); } put_device(&sdev->sdev_gendev); @@ -1544,6 +1561,12 @@ static inline int scsi_dev_queue_ready(struct request_queue *q, return 1; out_dec: atomic_dec(&sdev->device_busy); + + if (unlikely(scsi_is_admin_queue(q))) { + spin_lock_irq(sdev->host->host_lock); + sdev->host->run_admin_queue = true; + spin_unlock_irq(sdev->host->host_lock); + } return 0; } @@ -1552,7 +1575,7 @@ static inline int scsi_dev_queue_ready(struct request_queue *q, * @sdev: scsi device on starget to check. */ static inline int scsi_target_queue_ready(struct Scsi_Host *shost, - struct scsi_device *sdev) + struct scsi_device *sdev, bool admin) { struct scsi_target *starget = scsi_target(sdev); unsigned int busy; @@ -1594,6 +1617,8 @@ static inline int scsi_target_queue_ready(struct Scsi_Host *shost, starved: spin_lock_irq(shost->host_lock); list_move_tail(&sdev->starved_entry, &shost->starved_list); + if (admin) + shost->run_admin_queue = true; spin_unlock_irq(shost->host_lock); out_dec: if (starget->can_queue > 0) @@ -1650,6 +1675,8 @@ static inline int scsi_host_queue_ready(struct request_queue *q, spin_lock_irq(shost->host_lock); if (list_empty(&sdev->starved_entry)) list_add_tail(&sdev->starved_entry, &shost->starved_list); + if (scsi_is_admin_queue(q)) + shost->run_admin_queue = true; spin_unlock_irq(shost->host_lock); out_dec: scsi_dec_host_busy(shost); @@ -1949,7 +1976,7 @@ static void scsi_request_fn(struct request_queue *q) goto not_ready; } - if (!scsi_target_queue_ready(shost, sdev)) + if (!scsi_target_queue_ready(shost, sdev, scsi_is_admin_queue(q))) goto not_ready; if (!scsi_host_queue_ready(q, shost, sdev)) @@ -2112,7 +2139,7 @@ static blk_status_t scsi_queue_rq(struct blk_mq_hw_ctx *hctx, goto out_put_budget; ret = BLK_STS_RESOURCE; - if (!scsi_target_queue_ready(shost, sdev)) + if (!scsi_target_queue_ready(shost, sdev, scsi_is_admin_queue(q))) goto out_put_budget; if (!scsi_host_queue_ready(q, shost, sdev)) goto out_dec_target_busy; diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index 5ea06d310a25..4896e6003aeb 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -532,6 +532,8 @@ struct Scsi_Host { struct list_head __devices; struct list_head __targets; + struct request_queue *admin_q; + bool run_admin_queue; struct list_head starved_list; spinlock_t default_lock;