All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 0/2] Rework blk_mq_mark_tag_wait()
@ 2018-01-10 21:41 Bart Van Assche
  2018-01-10 21:41 ` [PATCH v3 1/2] blk-mq: Reduce the number of if-statements in blk_mq_mark_tag_wait() Bart Van Assche
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Bart Van Assche @ 2018-01-10 21:41 UTC (permalink / raw)
  To: Jens Axboe; +Cc: linux-block, Christoph Hellwig, Bart Van Assche

Hello Jens,

This patch series reworks the blk_mq_mark_tag_wait() implementation and also
fixes a race condition in that function. Please consider these two patches for
kernel v4.16.

Thanks,

Bart.

Changes compared to v3:
- Reworked patch 1/2 such that it uses if (...) ...; ... instead of
  if (...) ... else ... as proposed by Jens.

Changes compared to v1:
- Split a single patch into two patches to make reviewing easier.
- The race fix does no longer use prepare_to_wait() / finish_wait().

Bart Van Assche (2):
  blk-mq: Reduce the number of if-statements in blk_mq_mark_tag_wait()
  blk-mq: Fix a race condition in blk_mq_mark_tag_wait()

 block/blk-mq.c | 72 +++++++++++++++++++++++++++++-----------------------------
 1 file changed, 36 insertions(+), 36 deletions(-)

-- 
2.15.1

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH v3 1/2] blk-mq: Reduce the number of if-statements in blk_mq_mark_tag_wait()
  2018-01-10 21:41 [PATCH v3 0/2] Rework blk_mq_mark_tag_wait() Bart Van Assche
@ 2018-01-10 21:41 ` Bart Van Assche
  2018-01-10 21:41 ` [PATCH v3 2/2] blk-mq: Fix a race condition " Bart Van Assche
  2018-01-11 17:00 ` [PATCH v3 0/2] Rework blk_mq_mark_tag_wait() Jens Axboe
  2 siblings, 0 replies; 4+ messages in thread
From: Bart Van Assche @ 2018-01-10 21:41 UTC (permalink / raw)
  To: Jens Axboe
  Cc: linux-block, Christoph Hellwig, Bart Van Assche, Omar Sandoval,
	Hannes Reinecke, Johannes Thumshirn

This patch does not change any functionality but makes the
blk_mq_mark_tag_wait() code slightly easier to read.

Signed-off-by: Bart Van Assche <bart.vanassche@wdc.com>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Omar Sandoval <osandov@fb.com>
Cc: Hannes Reinecke <hare@suse.de>
Cc: Johannes Thumshirn <jthumshirn@suse.de>
---
 block/blk-mq.c | 69 +++++++++++++++++++++++++++++-----------------------------
 1 file changed, 35 insertions(+), 34 deletions(-)

diff --git a/block/blk-mq.c b/block/blk-mq.c
index 1d705e25852e..f27bcb6f6751 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -1181,58 +1181,59 @@ static bool blk_mq_mark_tag_wait(struct blk_mq_hw_ctx **hctx,
 				 struct request *rq)
 {
 	struct blk_mq_hw_ctx *this_hctx = *hctx;
-	bool shared_tags = (this_hctx->flags & BLK_MQ_F_TAG_SHARED) != 0;
 	struct sbq_wait_state *ws;
 	wait_queue_entry_t *wait;
 	bool ret;
 
-	if (!shared_tags) {
+	if (!(this_hctx->flags & BLK_MQ_F_TAG_SHARED)) {
 		if (!test_bit(BLK_MQ_S_SCHED_RESTART, &this_hctx->state))
 			set_bit(BLK_MQ_S_SCHED_RESTART, &this_hctx->state);
-	} else {
-		wait = &this_hctx->dispatch_wait;
-		if (!list_empty_careful(&wait->entry))
-			return false;
 
-		spin_lock(&this_hctx->lock);
-		if (!list_empty(&wait->entry)) {
-			spin_unlock(&this_hctx->lock);
-			return false;
-		}
+		/*
+		 * It's possible that a tag was freed in the window between the
+		 * allocation failure and adding the hardware queue to the wait
+		 * queue.
+		 *
+		 * Don't clear RESTART here, someone else could have set it.
+		 * At most this will cost an extra queue run.
+		 */
+		return blk_mq_get_driver_tag(rq, hctx, false);
+	}
+
+	wait = &this_hctx->dispatch_wait;
+	if (!list_empty_careful(&wait->entry))
+		return false;
 
-		ws = bt_wait_ptr(&this_hctx->tags->bitmap_tags, this_hctx);
-		add_wait_queue(&ws->wait, wait);
+	spin_lock(&this_hctx->lock);
+	if (!list_empty(&wait->entry)) {
+		spin_unlock(&this_hctx->lock);
+		return false;
 	}
 
+	ws = bt_wait_ptr(&this_hctx->tags->bitmap_tags, this_hctx);
+	add_wait_queue(&ws->wait, wait);
+
 	/*
 	 * It's possible that a tag was freed in the window between the
 	 * allocation failure and adding the hardware queue to the wait
 	 * queue.
 	 */
 	ret = blk_mq_get_driver_tag(rq, hctx, false);
-
-	if (!shared_tags) {
-		/*
-		 * Don't clear RESTART here, someone else could have set it.
-		 * At most this will cost an extra queue run.
-		 */
-		return ret;
-	} else {
-		if (!ret) {
-			spin_unlock(&this_hctx->lock);
-			return false;
-		}
-
-		/*
-		 * We got a tag, remove ourselves from the wait queue to ensure
-		 * someone else gets the wakeup.
-		 */
-		spin_lock_irq(&ws->wait.lock);
-		list_del_init(&wait->entry);
-		spin_unlock_irq(&ws->wait.lock);
+	if (!ret) {
 		spin_unlock(&this_hctx->lock);
-		return true;
+		return false;
 	}
+
+	/*
+	 * We got a tag, remove ourselves from the wait queue to ensure
+	 * someone else gets the wakeup.
+	 */
+	spin_lock_irq(&ws->wait.lock);
+	list_del_init(&wait->entry);
+	spin_unlock_irq(&ws->wait.lock);
+	spin_unlock(&this_hctx->lock);
+
+	return true;
 }
 
 bool blk_mq_dispatch_rq_list(struct request_queue *q, struct list_head *list,
-- 
2.15.1

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH v3 2/2] blk-mq: Fix a race condition in blk_mq_mark_tag_wait()
  2018-01-10 21:41 [PATCH v3 0/2] Rework blk_mq_mark_tag_wait() Bart Van Assche
  2018-01-10 21:41 ` [PATCH v3 1/2] blk-mq: Reduce the number of if-statements in blk_mq_mark_tag_wait() Bart Van Assche
@ 2018-01-10 21:41 ` Bart Van Assche
  2018-01-11 17:00 ` [PATCH v3 0/2] Rework blk_mq_mark_tag_wait() Jens Axboe
  2 siblings, 0 replies; 4+ messages in thread
From: Bart Van Assche @ 2018-01-10 21:41 UTC (permalink / raw)
  To: Jens Axboe
  Cc: linux-block, Christoph Hellwig, Bart Van Assche, Omar Sandoval,
	Hannes Reinecke, Johannes Thumshirn

Both add_wait_queue() and blk_mq_dispatch_wake() protect wait queue
manipulations with the wait queue lock. Hence also protect the
!list_empty(&wait->entry) test with the wait queue lock.

Signed-off-by: Bart Van Assche <bart.vanassche@wdc.com>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Omar Sandoval <osandov@fb.com>
Cc: Hannes Reinecke <hare@suse.de>
Cc: Johannes Thumshirn <jthumshirn@suse.de>
---
 block/blk-mq.c | 19 +++++++++----------
 1 file changed, 9 insertions(+), 10 deletions(-)

diff --git a/block/blk-mq.c b/block/blk-mq.c
index f27bcb6f6751..bbadbd5c8003 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -1183,7 +1183,7 @@ static bool blk_mq_mark_tag_wait(struct blk_mq_hw_ctx **hctx,
 	struct blk_mq_hw_ctx *this_hctx = *hctx;
 	struct sbq_wait_state *ws;
 	wait_queue_entry_t *wait;
-	bool ret;
+	bool on_wait_list, ret;
 
 	if (!(this_hctx->flags & BLK_MQ_F_TAG_SHARED)) {
 		if (!test_bit(BLK_MQ_S_SCHED_RESTART, &this_hctx->state))
@@ -1204,13 +1204,15 @@ static bool blk_mq_mark_tag_wait(struct blk_mq_hw_ctx **hctx,
 	if (!list_empty_careful(&wait->entry))
 		return false;
 
-	spin_lock(&this_hctx->lock);
-	if (!list_empty(&wait->entry)) {
-		spin_unlock(&this_hctx->lock);
+	ws = bt_wait_ptr(&this_hctx->tags->bitmap_tags, this_hctx);
+
+	spin_lock_irq(&ws->wait.lock);
+	on_wait_list = !list_empty(&wait->entry);
+	spin_unlock_irq(&ws->wait.lock);
+
+	if (on_wait_list)
 		return false;
-	}
 
-	ws = bt_wait_ptr(&this_hctx->tags->bitmap_tags, this_hctx);
 	add_wait_queue(&ws->wait, wait);
 
 	/*
@@ -1219,10 +1221,8 @@ static bool blk_mq_mark_tag_wait(struct blk_mq_hw_ctx **hctx,
 	 * queue.
 	 */
 	ret = blk_mq_get_driver_tag(rq, hctx, false);
-	if (!ret) {
-		spin_unlock(&this_hctx->lock);
+	if (!ret)
 		return false;
-	}
 
 	/*
 	 * We got a tag, remove ourselves from the wait queue to ensure
@@ -1231,7 +1231,6 @@ static bool blk_mq_mark_tag_wait(struct blk_mq_hw_ctx **hctx,
 	spin_lock_irq(&ws->wait.lock);
 	list_del_init(&wait->entry);
 	spin_unlock_irq(&ws->wait.lock);
-	spin_unlock(&this_hctx->lock);
 
 	return true;
 }
-- 
2.15.1

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH v3 0/2] Rework blk_mq_mark_tag_wait()
  2018-01-10 21:41 [PATCH v3 0/2] Rework blk_mq_mark_tag_wait() Bart Van Assche
  2018-01-10 21:41 ` [PATCH v3 1/2] blk-mq: Reduce the number of if-statements in blk_mq_mark_tag_wait() Bart Van Assche
  2018-01-10 21:41 ` [PATCH v3 2/2] blk-mq: Fix a race condition " Bart Van Assche
@ 2018-01-11 17:00 ` Jens Axboe
  2 siblings, 0 replies; 4+ messages in thread
From: Jens Axboe @ 2018-01-11 17:00 UTC (permalink / raw)
  To: Bart Van Assche; +Cc: linux-block, Christoph Hellwig

On 1/10/18 2:41 PM, Bart Van Assche wrote:
> Hello Jens,
> 
> This patch series reworks the blk_mq_mark_tag_wait() implementation and also
> fixes a race condition in that function. Please consider these two patches for
> kernel v4.16.

Applied 1/2 for now, need to mull over 2/2 a bit more.

-- 
Jens Axboe

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2018-01-11 17:00 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-01-10 21:41 [PATCH v3 0/2] Rework blk_mq_mark_tag_wait() Bart Van Assche
2018-01-10 21:41 ` [PATCH v3 1/2] blk-mq: Reduce the number of if-statements in blk_mq_mark_tag_wait() Bart Van Assche
2018-01-10 21:41 ` [PATCH v3 2/2] blk-mq: Fix a race condition " Bart Van Assche
2018-01-11 17:00 ` [PATCH v3 0/2] Rework blk_mq_mark_tag_wait() Jens Axboe

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.