All of lore.kernel.org
 help / color / mirror / Atom feed
From: Damien Le Moal <damien.lemoal@wdc.com>
To: linux-scsi@vger.kernel.org,
	"Martin K . Petersen" <martin.petersen@oracle.com>,
	linux-block@vger.kernel.org, Jens Axboe <axboe@kernel.dk>
Cc: Christoph Hellwig <hch@lst.de>, Bart Van Assche <Bart.VanAssche@wdc.com>
Subject: [PATCH V5 12/14] block: mq-deadline: Introduce zone locking support
Date: Mon, 25 Sep 2017 15:14:52 +0900	[thread overview]
Message-ID: <20170925061454.5533-13-damien.lemoal@wdc.com> (raw)
In-Reply-To: <20170925061454.5533-1-damien.lemoal@wdc.com>

For a write request to a zoned block device, lock the request target
zone upon request displatch. The zone is unlocked either when the
request completes or when the request is requeued (inserted).

To indicate that a request has locked its target zone, use the first
pointer of the request elevator private data to store the value
RQ_ZONE_WLOCKED. Testing for this value allows quick decision in
dd_insert_request() and dd_completed_request() regarding the need for
unlocking the target zone of a request.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 block/mq-deadline.c | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 114 insertions(+)

diff --git a/block/mq-deadline.c b/block/mq-deadline.c
index 296880e2471f..186c32099845 100644
--- a/block/mq-deadline.c
+++ b/block/mq-deadline.c
@@ -178,6 +178,93 @@ deadline_move_request(struct deadline_data *dd, struct request *rq)
 }
 
 /*
+ * Return true if a request is a write requests that needs zone
+ * write locking.
+ */
+static inline bool deadline_request_needs_zone_wlock(struct deadline_data *dd,
+						     struct request *rq)
+{
+
+	if (!dd->zones_wlock)
+		return false;
+
+	if (blk_rq_is_passthrough(rq))
+		return false;
+
+	switch (req_op(rq)) {
+	case REQ_OP_WRITE_ZEROES:
+	case REQ_OP_WRITE_SAME:
+	case REQ_OP_WRITE:
+		return blk_rq_zone_is_seq(rq);
+	default:
+		return false;
+	}
+}
+
+/*
+ * Abuse the elv.priv[0] pointer to indicate if a request has write
+ * locked its target zone. Only write request to a zoned block device
+ * can own a zone write lock.
+ */
+#define RQ_ZONE_WLOCKED		((void *)1UL)
+static inline void deadline_set_request_zone_wlock(struct request *rq)
+{
+	rq->elv.priv[0] = RQ_ZONE_WLOCKED;
+}
+
+#define RQ_ZONE_NO_WLOCK	((void *)0UL)
+static inline void deadline_clear_request_zone_wlock(struct request *rq)
+{
+	rq->elv.priv[0] = RQ_ZONE_NO_WLOCK;
+}
+
+static inline bool deadline_request_has_zone_wlock(struct request *rq)
+{
+	return rq->elv.priv[0] == RQ_ZONE_WLOCKED;
+}
+
+/*
+ * Write lock the target zone of a write request.
+ */
+static void deadline_wlock_zone(struct deadline_data *dd,
+				struct request *rq)
+{
+	unsigned int zno = blk_rq_zone_no(rq);
+
+	WARN_ON_ONCE(deadline_request_has_zone_wlock(rq));
+	WARN_ON_ONCE(test_and_set_bit(zno, dd->zones_wlock));
+	deadline_set_request_zone_wlock(rq);
+}
+
+/*
+ * Write unlock the target zone of a write request.
+ */
+static void deadline_wunlock_zone(struct deadline_data *dd,
+				  struct request *rq)
+{
+	unsigned int zno = blk_rq_zone_no(rq);
+	unsigned long flags;
+
+	spin_lock_irqsave(&dd->zone_lock, flags);
+
+	WARN_ON_ONCE(!test_and_clear_bit(zno, dd->zones_wlock));
+	deadline_clear_request_zone_wlock(rq);
+
+	spin_unlock_irqrestore(&dd->zone_lock, flags);
+}
+
+/*
+ * Test the write lock state of the target zone of a write request.
+ */
+static inline bool deadline_zone_is_wlocked(struct deadline_data *dd,
+					    struct request *rq)
+{
+	unsigned int zno = blk_rq_zone_no(rq);
+
+	return test_bit(zno, dd->zones_wlock);
+}
+
+/*
  * deadline_check_fifo returns 0 if there are no expired requests on the fifo,
  * 1 otherwise. Requires !list_empty(&dd->fifo_list[data_dir])
  */
@@ -316,6 +403,11 @@ static struct request *__dd_dispatch_request(struct blk_mq_hw_ctx *hctx)
 	dd->batching++;
 	deadline_move_request(dd, rq);
 done:
+	/*
+	 * If the request needs its target zone locked, do it.
+	 */
+	if (deadline_request_needs_zone_wlock(dd, rq))
+		deadline_wlock_zone(dd, rq);
 	rq->rq_flags |= RQF_STARTED;
 	return rq;
 }
@@ -466,6 +558,13 @@ static void dd_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq,
 	struct deadline_data *dd = q->elevator->elevator_data;
 	const int data_dir = rq_data_dir(rq);
 
+	/*
+	 * This may be a requeue of a request that has locked its
+	 * target zone. If this is the case, release the request zone lock.
+	 */
+	if (deadline_request_has_zone_wlock(rq))
+		deadline_wunlock_zone(dd, rq);
+
 	if (blk_mq_sched_try_insert_merge(q, rq))
 		return;
 
@@ -510,6 +609,20 @@ static void dd_insert_requests(struct blk_mq_hw_ctx *hctx,
 	spin_unlock(&dd->lock);
 }
 
+/*
+ * For zoned block devices, write unlock the target zone of
+ * completed write requests.
+ */
+static void dd_completed_request(struct request *rq)
+{
+
+	if (deadline_request_has_zone_wlock(rq)) {
+		struct deadline_data *dd = rq->q->elevator->elevator_data;
+
+		deadline_wunlock_zone(dd, rq);
+	}
+}
+
 static bool dd_has_work(struct blk_mq_hw_ctx *hctx)
 {
 	struct deadline_data *dd = hctx->queue->elevator->elevator_data;
@@ -711,6 +824,7 @@ static struct elevator_type mq_deadline = {
 	.ops.mq = {
 		.insert_requests	= dd_insert_requests,
 		.dispatch_request	= dd_dispatch_request,
+		.completed_request	= dd_completed_request,
 		.next_request		= elv_rb_latter_request,
 		.former_request		= elv_rb_former_request,
 		.bio_merge		= dd_bio_merge,
-- 
2.13.5

  parent reply	other threads:[~2017-09-25  6:14 UTC|newest]

Thread overview: 40+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-09-25  6:14 [PATCH V5 00/14] scsi-mq support for ZBC disks Damien Le Moal
2017-09-25  6:14 ` [PATCH V5 01/14] scsi: sd_zbc: Move ZBC declarations to scsi_proto.h Damien Le Moal
2017-09-25  6:14 ` [PATCH V5 02/14] scsi: sd_zbc: Fix comments and indentation Damien Le Moal
2017-10-02 23:01   ` Bart Van Assche
2017-10-02 23:01     ` Bart Van Assche
2017-09-25  6:14 ` [PATCH V5 03/14] scsi: sd_zbc: Rearrange code Damien Le Moal
2017-09-25 21:02   ` Bart Van Assche
2017-09-25 21:02     ` Bart Van Assche
2017-09-25  6:14 ` [PATCH V5 04/14] scsi: sd_zbc: Use well defined macros Damien Le Moal
2017-09-25  6:14 ` [PATCH V5 05/14] scsi: sd_zbc: Fix sd_zbc_read_zoned_characteristics() Damien Le Moal
2017-09-25  6:14 ` [PATCH V5 06/14] block: Add zoned block device information to request queue Damien Le Moal
2017-09-25 10:05   ` Ming Lei
2017-09-25 21:06   ` Bart Van Assche
2017-09-25 21:06     ` Bart Van Assche
2017-09-25  6:14 ` [PATCH V5 07/14] scsi: sd_zbc: Initialize device request queue zoned data Damien Le Moal
2017-09-25 21:17   ` Bart Van Assche
2017-09-25 21:17     ` Bart Van Assche
2017-10-02  4:29     ` Damien Le Moal
2017-10-02  4:29       ` Damien Le Moal
2017-09-25  6:14 ` [PATCH V5 08/14] scsi: sd_zbc: Limit zone write locking to sequential zones Damien Le Moal
2017-09-25  6:14 ` [PATCH V5 09/14] scsi: sd_zbc: Disable zone write locking with scsi-mq Damien Le Moal
2017-09-25  6:14 ` [PATCH V5 10/14] block: mq-deadline: Add zoned block device data Damien Le Moal
2017-09-25 21:34   ` Bart Van Assche
2017-09-25 21:34     ` Bart Van Assche
2017-10-02  4:32     ` Damien Le Moal
2017-10-02  4:32       ` Damien Le Moal
2017-09-25  6:14 ` [PATCH V5 11/14] blokc: mq-deadline: Introduce dispatch helpers Damien Le Moal
2017-09-25 21:44   ` Bart Van Assche
2017-09-25 21:44     ` Bart Van Assche
2017-09-25  6:14 ` Damien Le Moal [this message]
2017-09-25 22:00   ` [PATCH V5 12/14] block: mq-deadline: Introduce zone locking support Bart Van Assche
2017-09-25 22:00     ` Bart Van Assche
2017-10-02  4:36     ` Damien Le Moal
2017-10-02  4:36       ` Damien Le Moal
2017-09-25  6:14 ` [PATCH V5 13/14] block: mq-deadline: Limit write request dispatch for zoned block devices Damien Le Moal
2017-09-25 22:06   ` Bart Van Assche
2017-09-25 22:06     ` Bart Van Assche
2017-10-02  4:38     ` Damien Le Moal
2017-10-02  4:38       ` Damien Le Moal
2017-09-25  6:14 ` [PATCH V5 14/14] block: do not set mq default scheduler Damien Le Moal

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170925061454.5533-13-damien.lemoal@wdc.com \
    --to=damien.lemoal@wdc.com \
    --cc=Bart.VanAssche@wdc.com \
    --cc=axboe@kernel.dk \
    --cc=hch@lst.de \
    --cc=linux-block@vger.kernel.org \
    --cc=linux-scsi@vger.kernel.org \
    --cc=martin.petersen@oracle.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.