summaryrefslogtreecommitdiff
path: root/block
diff options
context:
space:
mode:
authorYu Kuai <yukuai3@huawei.com>2025-09-10 16:04:38 +0800
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2025-10-15 12:03:28 +0200
commit10bc65a048477ee906a6c6a8b85c167098f04f9a (patch)
treeee8a53a75bb0022ec4aeb803e739a897fdac9310 /block
parent5ae84131b0fee48dcd49d8a1f73e9d8f837d429f (diff)
downloadlinux-10bc65a048477ee906a6c6a8b85c167098f04f9a.tar.gz
linux-10bc65a048477ee906a6c6a8b85c167098f04f9a.tar.bz2
linux-10bc65a048477ee906a6c6a8b85c167098f04f9a.zip
blk-mq: check invalid nr_requests in queue_requests_store()
[ Upstream commit b46d4c447db76e36906ed59ebb9b3ef8f3383322 ] queue_requests_store() is the only caller of blk_mq_update_nr_requests(), and blk_mq_update_nr_requests() is the only caller of blk_mq_tag_update_depth(), however, they all have checkings for nr_requests input by user. Make code cleaner by moving all the checkings to the top function: 1) nr_requests > reserved tags; 2) if there is elevator, 4 <= nr_requests <= 2048; 3) if elevator is none, 4 <= nr_requests <= tag_set->queue_depth; Meanwhile, case 2 is the only case tags can grow and -ENOMEM might be returned. Signed-off-by: Yu Kuai <yukuai3@huawei.com> Reviewed-by: Nilay Shroff <nilay@linux.ibm.com> Signed-off-by: Jens Axboe <axboe@kernel.dk> Stable-dep-of: b86433721f46 ("blk-mq: fix potential deadlock while nr_requests grown") Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'block')
-rw-r--r--block/blk-mq-tag.c16
-rw-r--r--block/blk-mq.c8
-rw-r--r--block/blk-mq.h2
-rw-r--r--block/blk-sysfs.c13
4 files changed, 17 insertions, 22 deletions
diff --git a/block/blk-mq-tag.c b/block/blk-mq-tag.c
index 5cffa5668d0c..725210f27471 100644
--- a/block/blk-mq-tag.c
+++ b/block/blk-mq-tag.c
@@ -584,14 +584,10 @@ void blk_mq_free_tags(struct blk_mq_tags *tags)
}
int blk_mq_tag_update_depth(struct blk_mq_hw_ctx *hctx,
- struct blk_mq_tags **tagsptr, unsigned int tdepth,
- bool can_grow)
+ struct blk_mq_tags **tagsptr, unsigned int tdepth)
{
struct blk_mq_tags *tags = *tagsptr;
- if (tdepth <= tags->nr_reserved_tags)
- return -EINVAL;
-
/*
* If we are allowed to grow beyond the original size, allocate
* a new set of tags before freeing the old one.
@@ -600,16 +596,6 @@ int blk_mq_tag_update_depth(struct blk_mq_hw_ctx *hctx,
struct blk_mq_tag_set *set = hctx->queue->tag_set;
struct blk_mq_tags *new;
- if (!can_grow)
- return -EINVAL;
-
- /*
- * We need some sort of upper limit, set it high enough that
- * no valid use cases should require more.
- */
- if (tdepth > MAX_SCHED_RQ)
- return -EINVAL;
-
/*
* Only the sbitmap needs resizing since we allocated the max
* initially.
diff --git a/block/blk-mq.c b/block/blk-mq.c
index f5e713224d81..a81ef562014d 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -4932,9 +4932,6 @@ int blk_mq_update_nr_requests(struct request_queue *q, unsigned int nr)
int ret = 0;
unsigned long i;
- if (q->nr_requests == nr)
- return 0;
-
blk_mq_quiesce_queue(q);
queue_for_each_hw_ctx(q, hctx, i) {
@@ -4946,10 +4943,9 @@ int blk_mq_update_nr_requests(struct request_queue *q, unsigned int nr)
*/
if (hctx->sched_tags) {
ret = blk_mq_tag_update_depth(hctx, &hctx->sched_tags,
- nr, true);
+ nr);
} else {
- ret = blk_mq_tag_update_depth(hctx, &hctx->tags, nr,
- false);
+ ret = blk_mq_tag_update_depth(hctx, &hctx->tags, nr);
}
if (ret)
goto out;
diff --git a/block/blk-mq.h b/block/blk-mq.h
index affb2e14b56e..2b3ade60c90b 100644
--- a/block/blk-mq.h
+++ b/block/blk-mq.h
@@ -171,7 +171,7 @@ void blk_mq_put_tag(struct blk_mq_tags *tags, struct blk_mq_ctx *ctx,
unsigned int tag);
void blk_mq_put_tags(struct blk_mq_tags *tags, int *tag_array, int nr_tags);
int blk_mq_tag_update_depth(struct blk_mq_hw_ctx *hctx,
- struct blk_mq_tags **tags, unsigned int depth, bool can_grow);
+ struct blk_mq_tags **tags, unsigned int depth);
void blk_mq_tag_resize_shared_tags(struct blk_mq_tag_set *set,
unsigned int size);
void blk_mq_tag_update_sched_shared_tags(struct request_queue *q);
diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c
index 4a7f1a349998..b61e956a868e 100644
--- a/block/blk-sysfs.c
+++ b/block/blk-sysfs.c
@@ -78,12 +78,25 @@ queue_requests_store(struct gendisk *disk, const char *page, size_t count)
memflags = blk_mq_freeze_queue(q);
mutex_lock(&q->elevator_lock);
+
+ if (nr == q->nr_requests)
+ goto unlock;
+
if (nr < BLKDEV_MIN_RQ)
nr = BLKDEV_MIN_RQ;
+ if (nr <= q->tag_set->reserved_tags ||
+ (q->elevator && nr > MAX_SCHED_RQ) ||
+ (!q->elevator && nr > q->tag_set->queue_depth)) {
+ ret = -EINVAL;
+ goto unlock;
+ }
+
err = blk_mq_update_nr_requests(disk->queue, nr);
if (err)
ret = err;
+
+unlock:
mutex_unlock(&q->elevator_lock);
blk_mq_unfreeze_queue(q, memflags);
return ret;