Skip to content

Commit eb212dc

Browse files
author
Ming Lei
committed
block: add new helper for disabling elevator switch when deleting disk
JIRA: https://issues.redhat.com/browse/RHEL-112997 commit 21eed79 Author: Ming Lei <[email protected]> Date: Mon May 5 22:17:58 2025 +0800 block: add new helper for disabling elevator switch when deleting disk Add new helper disable_elv_switch() and new flag QUEUE_FLAG_NO_ELV_SWITCH for disabling elevator switch before deleting disk: - originally flag QUEUE_FLAG_REGISTERED is added for preventing elevator switch during removing disk, but this flag has been used widely for other purposes, so add one new flag for disabling elevator switch only - for avoiding deadlock risk, we have to move elevator queue register/unregister out of elevator lock and queue freeze, which will be done in next patch. However, this way adds small race window between elevator switch and deleting ->queue_kobj, in which elevator queue register/unregister could be run concurrently. The added helper will be used for avoiding the race in the following patch. - drain in-progress elevator switch before deleting disk Suggested-by: Nilay Shroff <[email protected]> Reviewed-by: Christoph Hellwig <[email protected]> Reviewed-by: Hannes Reinecke <[email protected]> Signed-off-by: Ming Lei <[email protected]> Reviewed-by: Nilay Shroff <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jens Axboe <[email protected]> Signed-off-by: Ming Lei <[email protected]>
1 parent 7795da1 commit eb212dc

File tree

4 files changed

+27
-3
lines changed

4 files changed

+27
-3
lines changed

block/blk-mq-debugfs.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ static const char *const blk_queue_flag_name[] = {
9494
QUEUE_FLAG_NAME(HCTX_ACTIVE),
9595
QUEUE_FLAG_NAME(SQ_SCHED),
9696
QUEUE_FLAG_NAME(DISABLE_WBT_DEF),
97+
QUEUE_FLAG_NAME(NO_ELV_SWITCH),
9798
};
9899
#undef QUEUE_FLAG_NAME
99100

block/elevator.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -680,6 +680,9 @@ void elevator_set_default(struct request_queue *q)
680680
};
681681
int err = 0;
682682

683+
/* now we allow to switch elevator */
684+
blk_queue_flag_clear(QUEUE_FLAG_NO_ELV_SWITCH, q);
685+
683686
if (q->tag_set->flags & BLK_MQ_F_NO_SCHED_BY_DEFAULT)
684687
return;
685688

@@ -744,9 +747,13 @@ ssize_t elv_iosched_store(struct gendisk *disk, const char *buf,
744747
elv_iosched_load_module(ctx.name);
745748

746749
down_read(&set->update_nr_hwq_lock);
747-
ret = elevator_change(q, &ctx);
748-
if (!ret)
749-
ret = count;
750+
if (!blk_queue_no_elv_switch(q)) {
751+
ret = elevator_change(q, &ctx);
752+
if (!ret)
753+
ret = count;
754+
} else {
755+
ret = -ENOENT;
756+
}
750757
up_read(&set->update_nr_hwq_lock);
751758
return ret;
752759
}

block/genhd.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -757,6 +757,16 @@ static void __del_gendisk(struct gendisk *disk)
757757
blk_unfreeze_release_lock(q);
758758
}
759759

760+
static void disable_elv_switch(struct request_queue *q)
761+
{
762+
struct blk_mq_tag_set *set = q->tag_set;
763+
WARN_ON_ONCE(!queue_is_mq(q));
764+
765+
down_write(&set->update_nr_hwq_lock);
766+
blk_queue_flag_set(QUEUE_FLAG_NO_ELV_SWITCH, q);
767+
up_write(&set->update_nr_hwq_lock);
768+
}
769+
760770
/**
761771
* del_gendisk - remove the gendisk
762772
* @disk: the struct gendisk to remove
@@ -785,6 +795,9 @@ void del_gendisk(struct gendisk *disk)
785795
__del_gendisk(disk);
786796
} else {
787797
set = disk->queue->tag_set;
798+
799+
disable_elv_switch(disk->queue);
800+
788801
memflags = memalloc_noio_save();
789802
down_read(&set->update_nr_hwq_lock);
790803
__del_gendisk(disk);

include/linux/blkdev.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -653,6 +653,7 @@ enum {
653653
QUEUE_FLAG_HCTX_ACTIVE, /* at least one blk-mq hctx is active */
654654
QUEUE_FLAG_SQ_SCHED, /* single queue style io dispatch */
655655
QUEUE_FLAG_DISABLE_WBT_DEF, /* for sched to disable/enable wbt */
656+
QUEUE_FLAG_NO_ELV_SWITCH, /* can't switch elevator any more */
656657
QUEUE_FLAG_MAX
657658
};
658659

@@ -690,6 +691,8 @@ void blk_queue_flag_clear(unsigned int flag, struct request_queue *q);
690691
((q)->limits.features & BLK_FEAT_SKIP_TAGSET_QUIESCE)
691692
#define blk_queue_disable_wbt(q) \
692693
test_bit(QUEUE_FLAG_DISABLE_WBT_DEF, &(q)->queue_flags)
694+
#define blk_queue_no_elv_switch(q) \
695+
test_bit(QUEUE_FLAG_NO_ELV_SWITCH, &(q)->queue_flags)
693696

694697
extern void blk_set_pm_only(struct request_queue *q);
695698
extern void blk_clear_pm_only(struct request_queue *q);

0 commit comments

Comments
 (0)