Rust for Linux List
 help / color / mirror / Atom feed
* Re: [PATCH 36/98] blk-mq: quiesce a queue that joins a quiesced tag set
       [not found] ` <20261028164415.1262013-37-axboe@kernel.dk>
@ 2026-10-30 22:37   ` Nathan Chancellor
  0 siblings, 0 replies; only message in thread
From: Nathan Chancellor @ 2026-10-30 22:37 UTC (permalink / raw)
  To: Jens Axboe, Andreas Hindborg, Boqun Feng, Miguel Ojeda, Gary Guo
  Cc: linux-block, Josef Bacik, rust-for-linux

Hi Rust for Linux folks,

I only added a small subset of you plus the mailing list, if I missed
anybody, please bring them in as necessary.

On Wed, Oct 28, 2026 at 10:41:39AM -0600, Jens Axboe wrote:
> From: Josef Bacik <josef@toxicpanda.com>
> 
> blk_mq_quiesce_tagset() only quiesces the queues on the list at that
> moment. A queue added before blk_mq_unquiesce_tagset() runs unquiesced,
> and then gets unquiesced without ever having been quiesced, which trips
> the warning in blk_mq_unquiesce_queue(). NVMe gets there when a
> controller fails while its namespaces are being scanned.
> 
> Count the quiesce calls in the tag set and quiesce a joining queue that
> many times, under a spinlock that also serializes the two functions. It
> can't be tag_list_lock, see commit 59e25ef2b413.
> 
> Fixes: 414dd48e882c ("blk-mq: add tagset quiesce interface")
> Signed-off-by: Josef Bacik <josef@toxicpanda.com>
> Signed-off-by: Jens Axboe <axboe@kernel.dk>

After this patch landed in -next as commit 71ec3c7d6db8 ("blk-mq:
quiesce a queue that joins a quiesced tag set"), I am seeing the
following build error:

  $ make -skj"$(nproc)" ARCH=x86_64 LLVM=1 mrproper allmodconfig rust/kernel.o
  error[E0277]: the trait bound `bindings::__BindgenOpaqueArray8<[u8; 72]>: pin_init::Zeroable` is not satisfied
      --> rust/kernel/block/mq/tag_set.rs:41:49
       |
    41 |         let tag_set: bindings::blk_mq_tag_set = pin_init::zeroed();
       |                                                 ^^^^^^^^^^^^^^^^^^ the trait `pin_init::Zeroable` is not implemented for `bindings::__BindgenOpaqueArray8<[u8; 72]>`
       |
       = help: the following other types implement trait `pin_init::Zeroable`:
                 ()
                 (A, B, C, D, E, F, G, H, I, J)
                 (B, C, D, E, F, G, H, I, J)
                 (C, D, E, F, G, H, I, J)
                 (D, E, F, G, H, I, J)
                 (E, F, G, H, I, J)
                 (F, G, H, I, J)
                 (G, H, I, J)
               and 6359 others
       = note: required for `bindings::spinlock` to implement `pin_init::Zeroable`
       = note: 1 redundant requirement hidden
       = note: required for `blk_mq_tag_set` to implement `pin_init::Zeroable`
  note: required by a bound in `pin_init::zeroed`
      --> rust/pin-init/src/lib.rs:1688:24
       |
  1688 | pub const fn zeroed<T: Zeroable>() -> T {
       |                        ^^^^^^^^ required by this bound in `zeroed`

  error: aborting due to 1 previous error

  For more information about this error, try `rustc --explain E0277`.
  make[4]: *** [rust/Makefile:799: rust/kernel.o] Error 1
  ...

> ---
>  block/blk-mq.c         | 22 ++++++++++++++++++++++
>  include/linux/blk-mq.h |  6 ++++++
>  2 files changed, 28 insertions(+)
> 
> diff --git a/block/blk-mq.c b/block/blk-mq.c
> index 6d3ea97f9a00..0e8449424c9a 100644
> --- a/block/blk-mq.c
> +++ b/block/blk-mq.c
> @@ -336,12 +336,15 @@ void blk_mq_quiesce_tagset(struct blk_mq_tag_set *set)
>  {
>  	struct request_queue *q;
>  
> +	spin_lock(&set->quiesce_lock);
> +	set->quiesce_depth++;
>  	rcu_read_lock();
>  	list_for_each_entry_rcu(q, &set->tag_list, tag_set_list) {
>  		if (!blk_queue_skip_tagset_quiesce(q))
>  			blk_mq_quiesce_queue_nowait(q);
>  	}
>  	rcu_read_unlock();
> +	spin_unlock(&set->quiesce_lock);
>  
>  	blk_mq_wait_quiesce_done(set);
>  }
> @@ -351,12 +354,16 @@ void blk_mq_unquiesce_tagset(struct blk_mq_tag_set *set)
>  {
>  	struct request_queue *q;
>  
> +	spin_lock(&set->quiesce_lock);
> +	if (set->quiesce_depth)
> +		set->quiesce_depth--;
>  	rcu_read_lock();
>  	list_for_each_entry_rcu(q, &set->tag_list, tag_set_list) {
>  		if (!blk_queue_skip_tagset_quiesce(q))
>  			blk_mq_unquiesce_queue(q);
>  	}
>  	rcu_read_unlock();
> +	spin_unlock(&set->quiesce_lock);
>  }
>  EXPORT_SYMBOL_GPL(blk_mq_unquiesce_tagset);
>  
> @@ -4346,6 +4353,8 @@ static void blk_mq_del_queue_tag_set(struct request_queue *q)
>  static void blk_mq_add_queue_tag_set(struct blk_mq_tag_set *set,
>  				     struct request_queue *q)
>  {
> +	unsigned int i;
> +
>  	mutex_lock(&set->tag_list_lock);
>  
>  	/*
> @@ -4359,7 +4368,18 @@ static void blk_mq_add_queue_tag_set(struct blk_mq_tag_set *set,
>  	}
>  	if (set->flags & BLK_MQ_F_TAG_QUEUE_SHARED)
>  		queue_set_hctx_shared(q, true);
> +
> +	/*
> +	 * A queue that joins a quiesced tag set is quiesced like the others,
> +	 * and blk_mq_unquiesce_tagset() finds what it is going to undo.
> +	 */
> +	spin_lock(&set->quiesce_lock);
>  	list_add_tail_rcu(&q->tag_set_list, &set->tag_list);
> +	if (!blk_queue_skip_tagset_quiesce(q)) {
> +		for (i = 0; i < set->quiesce_depth; i++)
> +			blk_mq_quiesce_queue_nowait(q);
> +	}
> +	spin_unlock(&set->quiesce_lock);
>  
>  	mutex_unlock(&set->tag_list_lock);
>  }
> @@ -4928,6 +4948,8 @@ int blk_mq_alloc_tag_set(struct blk_mq_tag_set *set)
>  
>  	mutex_init(&set->tag_list_lock);
>  	INIT_LIST_HEAD(&set->tag_list);
> +	spin_lock_init(&set->quiesce_lock);
> +	set->quiesce_depth = 0;
>  
>  	return 0;
>  
> diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h
> index 5e130b282b42..aa3b35405edc 100644
> --- a/include/linux/blk-mq.h
> +++ b/include/linux/blk-mq.h
> @@ -523,6 +523,10 @@ enum hctx_type {
>   * @tag_list_lock: Serializes tag_list accesses.
>   * @tag_list:	   List of the request queues that use this tag set. See also
>   *		   request_queue.tag_set_list.
> + * @quiesce_lock:  Serializes blk_mq_[un]quiesce_tagset() against each other
> + *		   and against a request queue being added to @tag_list.
> + * @quiesce_depth: How often blk_mq_quiesce_tagset() has been called without
> + *		   blk_mq_unquiesce_tagset().
>   * @srcu:	   Use as lock when type of the request queue is blocking
>   *		   (BLK_MQ_F_BLOCKING).
>   * @update_nr_hwq_lock:
> @@ -548,6 +552,8 @@ struct blk_mq_tag_set {
>  
>  	struct mutex		tag_list_lock;
>  	struct list_head	tag_list;
> +	spinlock_t		quiesce_lock;
> +	unsigned int		quiesce_depth;
>  	struct srcu_struct	*srcu;
>  
>  	struct rw_semaphore	update_nr_hwq_lock;
> -- 
> 2.56.0
> 

-- 
Cheers,
Nathan

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2026-10-30 22:37 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <20261028164415.1262013-1-axboe@kernel.dk>
     [not found] ` <20261028164415.1262013-37-axboe@kernel.dk>
2026-10-30 22:37   ` [PATCH 36/98] blk-mq: quiesce a queue that joins a quiesced tag set Nathan Chancellor

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox