]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
blk-mq: check invalid nr_requests in queue_requests_store()
authorYu Kuai <yukuai3@huawei.com>
Wed, 10 Sep 2025 08:04:38 +0000 (16:04 +0800)
committerJens Axboe <axboe@kernel.dk>
Wed, 10 Sep 2025 11:25:56 +0000 (05:25 -0600)
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>
block/blk-mq-tag.c
block/blk-mq.c
block/blk-mq.h
block/blk-sysfs.c

index 086c67849e064addcca814d5191bde690bb85353..56f9bc839000a32d322b8372f436bde73e429c19 100644 (file)
@@ -610,14 +610,10 @@ void blk_mq_free_tags(struct blk_mq_tag_set *set, 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.
@@ -626,16 +622,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.
index 55ccc9f4435d9d024404cc72f9c584b38bceb4e9..9b97f2f3f2c90c573ef267d61552d727eceb20e3 100644 (file)
@@ -4933,9 +4933,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) {
@@ -4947,10 +4944,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;
index b96a753809abac59be1f51580fab4056961abfc4..5d42c7d3a952f0c392395f134c1e36d383a19314 100644 (file)
@@ -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);
index 1ffa65feca4f62378cd0410aeca0911f0e9bc945..f99519f7a8201bd8c6beb93066ecff589861f333 100644 (file)
@@ -75,12 +75,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;