diff mbox

[2/7] block: Document more locking requirements

Message ID 20171201000848.2656-3-bart.vanassche@wdc.com (mailing list archive)
State New, archived
Headers show

Commit Message

Bart Van Assche Dec. 1, 2017, 12:08 a.m. UTC
This patch does not change any functionality.

Signed-off-by: Bart Van Assche <bart.vanassche@wdc.com>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Hannes Reinecke <hare@suse.de>
Cc: Johannes Thumshirn <jthumshirn@suse.de>
---
 block/blk-mq.c      | 13 +++++++++++--
 block/blk-timeout.c |  3 +++
 2 files changed, 14 insertions(+), 2 deletions(-)

Comments

Jens Axboe Dec. 1, 2017, 3:03 a.m. UTC | #1
On 11/30/2017 05:08 PM, Bart Van Assche wrote:
> This patch does not change any functionality.

Unless these actually found real bugs, I think it's pointless.
Add a comment. And this:
 
> @@ -1003,9 +1007,14 @@ bool blk_mq_get_driver_tag(struct request *rq, struct blk_mq_hw_ctx **hctx,
>  static int blk_mq_dispatch_wake(wait_queue_entry_t *wait, unsigned mode,
>  				int flags, void *key)
>  {
> -	struct blk_mq_hw_ctx *hctx;
> +	struct blk_mq_hw_ctx *hctx =
> +		container_of(wait, struct blk_mq_hw_ctx, dispatch_wait);
> +
> +#ifdef CONFIG_LOCKDEP
> +	struct sbq_wait_state *ws = bt_wait_ptr(&hctx->tags->bitmap_tags, hctx);
>  
> -	hctx = container_of(wait, struct blk_mq_hw_ctx, dispatch_wait);
> +	lockdep_assert_held(&ws->wait.lock);
> +#endif

we're definitely not doing.
Bart Van Assche Dec. 1, 2017, 5:05 p.m. UTC | #2
On Thu, 2017-11-30 at 20:03 -0700, Jens Axboe wrote:
> On 11/30/2017 05:08 PM, Bart Van Assche wrote:

> > This patch does not change any functionality.

> 

> Unless these actually found real bugs, I think it's pointless.

> Add a comment.

 
Hello Jens,

As you know lockdep_assert_held() statements are verified at runtime with
LOCKDEP enabled but comments not. Hence my preference for lockdep_assert_held()
over source code comments.

> And this:

>

> > @@ -1003,9 +1007,14 @@ bool blk_mq_get_driver_tag(struct request *rq, struct blk_mq_hw_ctx **hctx,

> >  static int blk_mq_dispatch_wake(wait_queue_entry_t *wait, unsigned mode,

> >  				int flags, void *key)

> >  {

> > -	struct blk_mq_hw_ctx *hctx;

> > +	struct blk_mq_hw_ctx *hctx =

> > +		container_of(wait, struct blk_mq_hw_ctx, dispatch_wait);

> > +

> > +#ifdef CONFIG_LOCKDEP

> > +	struct sbq_wait_state *ws = bt_wait_ptr(&hctx->tags->bitmap_tags, hctx);

> >  

> > -	hctx = container_of(wait, struct blk_mq_hw_ctx, dispatch_wait);

> > +	lockdep_assert_held(&ws->wait.lock);

> > +#endif

> 

> we're definitely not doing.


Can you explain me why you think the above is wrong? My understanding is
that the call chain for the above function is as follows:

blk_mq_tag_wakeup_all()
-> sbitmap_queue_wake_all()
  -> wake_up()
    -> __wake_up()
      -> __wake_up_common_lock()
        -> spin_lock_irqsave(&wq_head->lock, flags);
        -> __wake_up_common()
          -> list_for_each_entry_safe_from(curr, next, &wq_head->head, entry)
          ->   ret = curr->func(curr, mode, wake_flags, key)
        -> spin_unlock_irqrestore(&wq_head->lock, flags);

In other words, blk_mq_dispatch_wake() is called with the wait queue head
lock held.

Bart.
diff mbox

Patch

diff --git a/block/blk-mq.c b/block/blk-mq.c
index e1ca7661daa5..7f290a91a612 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -74,6 +74,8 @@  static bool blk_mq_hctx_has_pending(struct blk_mq_hw_ctx *hctx)
 static void blk_mq_hctx_mark_pending(struct blk_mq_hw_ctx *hctx,
 				     struct blk_mq_ctx *ctx)
 {
+	lockdep_assert_held(&ctx->lock);
+
 	if (!sbitmap_test_bit(&hctx->ctx_map, ctx->index_hw))
 		sbitmap_set_bit(&hctx->ctx_map, ctx->index_hw);
 }
@@ -81,6 +83,8 @@  static void blk_mq_hctx_mark_pending(struct blk_mq_hw_ctx *hctx,
 static void blk_mq_hctx_clear_pending(struct blk_mq_hw_ctx *hctx,
 				      struct blk_mq_ctx *ctx)
 {
+	lockdep_assert_held(&ctx->lock);
+
 	sbitmap_clear_bit(&hctx->ctx_map, ctx->index_hw);
 }
 
@@ -1003,9 +1007,14 @@  bool blk_mq_get_driver_tag(struct request *rq, struct blk_mq_hw_ctx **hctx,
 static int blk_mq_dispatch_wake(wait_queue_entry_t *wait, unsigned mode,
 				int flags, void *key)
 {
-	struct blk_mq_hw_ctx *hctx;
+	struct blk_mq_hw_ctx *hctx =
+		container_of(wait, struct blk_mq_hw_ctx, dispatch_wait);
+
+#ifdef CONFIG_LOCKDEP
+	struct sbq_wait_state *ws = bt_wait_ptr(&hctx->tags->bitmap_tags, hctx);
 
-	hctx = container_of(wait, struct blk_mq_hw_ctx, dispatch_wait);
+	lockdep_assert_held(&ws->wait.lock);
+#endif
 
 	list_del_init(&wait->entry);
 	blk_mq_run_hw_queue(hctx, true);
diff --git a/block/blk-timeout.c b/block/blk-timeout.c
index 764ecf9aeb30..77bf0c6e7c7e 100644
--- a/block/blk-timeout.c
+++ b/block/blk-timeout.c
@@ -77,6 +77,9 @@  ssize_t part_timeout_store(struct device *dev, struct device_attribute *attr,
  */
 void blk_delete_timer(struct request *req)
 {
+	lockdep_assert_held(req->q->queue_lock);
+	WARN_ON_ONCE(req->q->mq_ops);
+
 	list_del_init(&req->timeout_list);
 }