From patchwork Sat Aug 11 07:12:18 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ming Lei X-Patchwork-Id: 10563357 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 EED2A1057 for ; Sat, 11 Aug 2018 07:15:37 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D84F22A957 for ; Sat, 11 Aug 2018 07:15:37 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id CC0072AC2F; Sat, 11 Aug 2018 07:15:37 +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 1C6532A957 for ; Sat, 11 Aug 2018 07:15:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727149AbeHKJsu (ORCPT ); Sat, 11 Aug 2018 05:48:50 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:48754 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1727129AbeHKJst (ORCPT ); Sat, 11 Aug 2018 05:48:49 -0400 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id C3A5977153; Sat, 11 Aug 2018 07:15:34 +0000 (UTC) Received: from localhost (ovpn-12-20.pek2.redhat.com [10.72.12.20]) by smtp.corp.redhat.com (Postfix) with ESMTP id BB13E2026D74; Sat, 11 Aug 2018 07:15:25 +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: [RFC PATCH V2 15/17] SCSI: use admin queue to implement queue QUIESCE Date: Sat, 11 Aug 2018 15:12:18 +0800 Message-Id: <20180811071220.357-16-ming.lei@redhat.com> In-Reply-To: <20180811071220.357-1-ming.lei@redhat.com> References: <20180811071220.357-1-ming.lei@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.4 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.1]); Sat, 11 Aug 2018 07:15:34 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.1]); Sat, 11 Aug 2018 07:15:34 +0000 (UTC) for IP:'10.11.54.4' DOMAIN:'int-mx04.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'ming.lei@redhat.com' RCPT:'' Sender: linux-block-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-block@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP All admin commands are sent via per-host admin queue, so we can simply freeze the IO queue for quiescing scsi device. Also the current SCSI stack guarantees that any request originated from admin queue won't be called back to block layer via the associated IO queue, and it is always dealt with by the admin queue. So it is safe to submit admin request via admin queue when the associated IO queue is frozen, and this way matches the PREEMPT flag perfectly. Finally, we can remove the preempt_only approach for supporting SCSI quiesce, then the code in block fast path is simplified a lot. 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 --- block/blk-core.c | 44 ++------------------------------------------ block/blk-mq-debugfs.c | 1 - drivers/scsi/scsi_lib.c | 29 +++-------------------------- include/linux/blkdev.h | 6 ------ include/scsi/scsi_device.h | 1 - 5 files changed, 5 insertions(+), 76 deletions(-) diff --git a/block/blk-core.c b/block/blk-core.c index 12550340418d..67d34a43359f 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -421,26 +421,6 @@ void blk_sync_queue(struct request_queue *q) EXPORT_SYMBOL(blk_sync_queue); /** - * blk_set_preempt_only - set QUEUE_FLAG_PREEMPT_ONLY - * @q: request queue pointer - * - * Returns the previous value of the PREEMPT_ONLY flag - 0 if the flag was not - * set and 1 if the flag was already set. - */ -int blk_set_preempt_only(struct request_queue *q) -{ - return blk_queue_flag_test_and_set(QUEUE_FLAG_PREEMPT_ONLY, q); -} -EXPORT_SYMBOL_GPL(blk_set_preempt_only); - -void blk_clear_preempt_only(struct request_queue *q) -{ - blk_queue_flag_clear(QUEUE_FLAG_PREEMPT_ONLY, q); - wake_up_all(&q->mq_freeze_wq); -} -EXPORT_SYMBOL_GPL(blk_clear_preempt_only); - -/** * __blk_run_queue_uncond - run a queue whether or not it has been stopped * @q: The queue to run * @@ -917,27 +897,8 @@ EXPORT_SYMBOL(blk_alloc_queue); */ int blk_queue_enter(struct request_queue *q, blk_mq_req_flags_t flags) { - const bool preempt = flags & BLK_MQ_REQ_PREEMPT; - while (true) { - bool success = false; - - rcu_read_lock(); - if (percpu_ref_tryget_live(&q->q_usage_counter)) { - /* - * The code that sets the PREEMPT_ONLY flag is - * responsible for ensuring that that flag is globally - * visible before the queue is unfrozen. - */ - if (preempt || !blk_queue_preempt_only(q)) { - success = true; - } else { - percpu_ref_put(&q->q_usage_counter); - } - } - rcu_read_unlock(); - - if (success) + if (percpu_ref_tryget_live(&q->q_usage_counter)) return 0; if (flags & BLK_MQ_REQ_NOWAIT) @@ -953,8 +914,7 @@ int blk_queue_enter(struct request_queue *q, blk_mq_req_flags_t flags) smp_rmb(); wait_event(q->mq_freeze_wq, - (atomic_read(&q->mq_freeze_depth) == 0 && - (preempt || !blk_queue_preempt_only(q))) || + atomic_read(&q->mq_freeze_depth) == 0 || blk_queue_dying(q)); if (blk_queue_dying(q)) return -ENODEV; diff --git a/block/blk-mq-debugfs.c b/block/blk-mq-debugfs.c index 8df013e9f242..82df43ec322f 100644 --- a/block/blk-mq-debugfs.c +++ b/block/blk-mq-debugfs.c @@ -132,7 +132,6 @@ static const char *const blk_queue_flag_name[] = { QUEUE_FLAG_NAME(REGISTERED), QUEUE_FLAG_NAME(SCSI_PASSTHROUGH), QUEUE_FLAG_NAME(QUIESCED), - QUEUE_FLAG_NAME(PREEMPT_ONLY), QUEUE_FLAG_NAME(ADMIN), }; #undef QUEUE_FLAG_NAME diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index ebd36ae549e8..965781e2879c 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -3130,34 +3130,12 @@ static void scsi_wait_for_queuecommand(struct scsi_device *sdev) int scsi_device_quiesce(struct scsi_device *sdev) { - struct request_queue *q = sdev->request_queue; int err; - /* - * It is allowed to call scsi_device_quiesce() multiple times from - * the same context but concurrent scsi_device_quiesce() calls are - * not allowed. - */ - WARN_ON_ONCE(sdev->quiesced_by && sdev->quiesced_by != current); - - blk_set_preempt_only(q); - - blk_mq_freeze_queue(q); - /* - * Ensure that the effect of blk_set_preempt_only() will be visible - * for percpu_ref_tryget() callers that occur after the queue - * unfreeze even if the queue was already frozen before this function - * was called. See also https://lwn.net/Articles/573497/. - */ - synchronize_rcu(); - blk_mq_unfreeze_queue(q); + blk_mq_freeze_queue(sdev->request_queue); mutex_lock(&sdev->state_mutex); err = scsi_device_set_state(sdev, SDEV_QUIESCE); - if (err == 0) - sdev->quiesced_by = current; - else - blk_clear_preempt_only(q); mutex_unlock(&sdev->state_mutex); return err; @@ -3180,12 +3158,11 @@ void scsi_device_resume(struct scsi_device *sdev) * device deleted during suspend) */ mutex_lock(&sdev->state_mutex); - WARN_ON_ONCE(!sdev->quiesced_by); - sdev->quiesced_by = NULL; - blk_clear_preempt_only(sdev->request_queue); if (sdev->sdev_state == SDEV_QUIESCE) scsi_device_set_state(sdev, SDEV_RUNNING); mutex_unlock(&sdev->state_mutex); + + blk_mq_unfreeze_queue(sdev->request_queue); } EXPORT_SYMBOL(scsi_device_resume); diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 2dbc7524a169..1bd4f02d11c0 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -698,7 +698,6 @@ struct request_queue { #define QUEUE_FLAG_REGISTERED 26 /* queue has been registered to a disk */ #define QUEUE_FLAG_SCSI_PASSTHROUGH 27 /* queue supports SCSI commands */ #define QUEUE_FLAG_QUIESCED 28 /* queue has been quiesced */ -#define QUEUE_FLAG_PREEMPT_ONLY 29 /* only process REQ_PREEMPT requests */ #define QUEUE_FLAG_ADMIN 30 /* admin queue */ #define QUEUE_FLAG_DEFAULT ((1 << QUEUE_FLAG_IO_STAT) | \ @@ -740,14 +739,9 @@ bool blk_queue_flag_test_and_clear(unsigned int flag, struct request_queue *q); ((rq)->cmd_flags & (REQ_FAILFAST_DEV|REQ_FAILFAST_TRANSPORT| \ REQ_FAILFAST_DRIVER)) #define blk_queue_quiesced(q) test_bit(QUEUE_FLAG_QUIESCED, &(q)->queue_flags) -#define blk_queue_preempt_only(q) \ - test_bit(QUEUE_FLAG_PREEMPT_ONLY, &(q)->queue_flags) #define blk_queue_fua(q) test_bit(QUEUE_FLAG_FUA, &(q)->queue_flags) #define blk_queue_admin(q) test_bit(QUEUE_FLAG_ADMIN, &(q)->queue_flags) -extern int blk_set_preempt_only(struct request_queue *q); -extern void blk_clear_preempt_only(struct request_queue *q); - static inline int queue_in_flight(struct request_queue *q) { return q->in_flight[0] + q->in_flight[1]; diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index f6820da1dc37..666b58799cec 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -226,7 +226,6 @@ struct scsi_device { unsigned char access_state; struct mutex state_mutex; enum scsi_device_state sdev_state; - struct task_struct *quiesced_by; atomic_t nr_admin_pending; wait_queue_head_t admin_wq;