mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Nilay Shroff <nilay@linux.ibm.com>
To: Laveesh Bansal <laveeshb@laveeshbansal.com>,
	Jens Axboe <axboe@kernel.dk>
Cc: "Shin'ichiro Kawasaki" <shinichiro.kawasaki@wdc.com>,
	Ming Lei <tom.leiming@gmail.com>, Christoph Hellwig <hch@lst.de>,
	Yu Kuai <yukuai@fygo.io>, Reindl Harald <h.reindl@thelounge.net>,
	linux-block@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH] block: only serialize elevator switches of the same queue
Date: Wed, 28 Oct 2026 17:51:26 +0530	[thread overview]
Message-ID: <7f697f9d-6e8c-4544-bca7-137d3f3d2dbf@linux.ibm.com> (raw)
In-Reply-To: <20261023201704.20577-1-laveeshb@laveeshbansal.com>

On 10/24/26 1:47 AM, Laveesh Bansal wrote:
> diff --git a/block/blk-core.c b/block/blk-core.c
> index 196bccf27f58..655c18237967 100644
> --- a/block/blk-core.c
> +++ b/block/blk-core.c
> @@ -473,6 +473,7 @@ struct request_queue *blk_alloc_queue(struct queue_limits *lim, int node_id)
>   	refcount_set(&q->refs, 1);
>   	mutex_init(&q->debugfs_mutex);
>   	mutex_init(&q->elevator_lock);
> +	mutex_init(&q->elevator_store_lock);
>   	mutex_init(&q->sysfs_lock);
>   	mutex_init(&q->limits_lock);
>   	mutex_init(&q->rq_qos_mutex);
> diff --git a/block/elevator.c b/block/elevator.c
> index 2161b6eea680..0a8fcb4bad06 100644
> --- a/block/elevator.c
> +++ b/block/elevator.c
> @@ -812,16 +812,16 @@ ssize_t elv_iosched_store(struct gendisk *disk, const char *buf,
>   	 * reference during concurrent disk deletion:
>   	 *   update_nr_hwq_lock -> kn->active (via del_gendisk -> kobject_del)
>   	 *   kn->active -> update_nr_hwq_lock (via this sysfs write path)
> -	 *
> -	 * Use the writer lock instead of the reader lock of update_nr_hwq_lock
> -	 * to serialize the two-stage elevator switch steps in
> -	 * elevator_change(): the core switch step under the elevator lock and
> -	 * the elevator_change_done() step outside the elevator lock.
>   	 */
> -	if (!down_write_trylock(&set->update_nr_hwq_lock)) {
> +	if (!down_read_trylock(&set->update_nr_hwq_lock)) {
>   		ret = -EBUSY;
>   		goto out;
>   	}
> +
> +	/* The reader lock is shared: serialize both stages of a switch here. */
> +	ret = mutex_lock_killable(&q->elevator_store_lock);

We generally try to avoid introducing new locks unless absolutely necessary.
Adding another lock to the generic block layer also introduces maintenance
overhead. In fact, we have been trying to eliminate some existing locks in
the block layer by restructuring the code where possible.

That said, I understand the issue you're trying to address. Instead of
introducing a new lock, I'd suggest using QUEUE_FLAG_NO_ELV_SWITCH in the
sysfs store path. The store path could atomically test and set this flag.
If the flag is already set, it means either another concurrent store
operation is in progress or the disk is being torn down. In either case,
the store operation can return -EBUSY. Based on this approach, I'd suggest
the following change:

diff --git a/block/elevator.c b/block/elevator.c
index 2161b6eea680..e59381922679 100644
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -812,25 +812,24 @@ ssize_t elv_iosched_store(struct gendisk *disk, const char *buf,
  	 * reference during concurrent disk deletion:
  	 *   update_nr_hwq_lock -> kn->active (via del_gendisk -> kobject_del)
  	 *   kn->active -> update_nr_hwq_lock (via this sysfs write path)
-	 *
-	 * Use the writer lock instead of the reader lock of update_nr_hwq_lock
-	 * to serialize the two-stage elevator switch steps in
-	 * elevator_change(): the core switch step under the elevator lock and
-	 * the elevator_change_done() step outside the elevator lock.
  	 */
-	if (!down_write_trylock(&set->update_nr_hwq_lock)) {
+	if (!down_read_trylock(&set->update_nr_hwq_lock)) {
  		ret = -EBUSY;
  		goto out;
  	}
-	if (!blk_queue_no_elv_switch(q)) {
-		ret = elevator_change(q, &ctx);
-		if (!ret)
-			ret = count;
-	} else {
-		ret = -ENOENT;
+
+	if (test_and_set_bit(QUEUE_FLAG_NO_ELV_SWITCH, &q->queue_flags)) {
+		ret = -EBUSY;
+		goto out_unlock;
  	}
-	up_write(&set->update_nr_hwq_lock);

+	ret = elevator_change(q, &ctx);
+	if (!ret)
+		ret = count;
+
+	clear_bit(QUEUE_FLAG_NO_ELV_SWITCH, &q->queue_flags);
+out_unlock:
+	up_read(&set->update_nr_hwq_lock);
  out:
  	if (ctx.type)
  		elevator_put(ctx.type);

Please note that I have only compile tested the above code. You may test it,
and update if this works for your case.

Thanks,
--Nilay

      parent reply	other threads:[~2026-10-28 12:22 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-23 20:17 Laveesh Bansal
2026-10-25 12:23 ` Shin'ichiro Kawasaki
2026-10-28 12:21 ` Nilay Shroff [this message]

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=7f697f9d-6e8c-4544-bca7-137d3f3d2dbf@linux.ibm.com \
    --to=nilay@linux.ibm.com \
    --cc=axboe@kernel.dk \
    --cc=h.reindl@thelounge.net \
    --cc=hch@lst.de \
    --cc=laveeshb@laveeshbansal.com \
    --cc=linux-block@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=shinichiro.kawasaki@wdc.com \
    --cc=tom.leiming@gmail.com \
    --cc=yukuai@fygo.io \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®