nvme: raise FDP placement handle cap to U8_MAX and warn on overflow

The RUH status buffer and the placement-handle clamp used S8_MAX - 1
(126) as the maximum descriptor count. That value was picked only so the
io-mgmt-receive result fit in a page, not because of any protocol or
driver restriction.

The meaningful upper bound is U8_MAX: write hints (bio->bi_write_stream)
are u8, so placement handles beyond U8_MAX can never be selected. Size
the buffer and clamp nr_plids to U8_MAX.

Suggested-by: Kanchan Joshi <joshi.k@samsung.com>
Signed-off-by: Guixin Liu <kanie@linux.alibaba.com>
Reviewed-by: Kanchan Joshi <joshi.k@samsung.com>
Reviewed-by: Nilay Shroff <nilay@linux.ibm.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Keith Busch <kbusch@kernel.org>
This commit is contained in:
Guixin Liu 2026-08-04 10:19:01 +08:00 committed by Keith Busch
parent cb144c2f67
commit 53cdaeab2e

View File

@ -33,6 +33,13 @@
#define NVME_MINORS (1U << MINORBITS)
/*
* Write hints (bio->bi_write_stream) are u8, so FDP placement handles beyond
* U8_MAX can never be selected. Cap the handle count to bound both the RUH
* status buffer and the per-head plids array.
*/
#define NVME_MAX_PLIDS U8_MAX
struct nvme_ns_info {
struct nvme_ns_ids ids;
u32 nsid;
@ -2353,7 +2360,7 @@ static int nvme_query_fdp_info(struct nvme_ns *ns, struct nvme_ns_info *info)
if (!info->runs)
return ret;
size = struct_size(ruhs, ruhsd, S8_MAX - 1);
size = struct_size(ruhs, ruhsd, NVME_MAX_PLIDS);
ruhs = kzalloc(size, GFP_KERNEL);
if (!ruhs)
return -ENOMEM;
@ -2368,7 +2375,7 @@ static int nvme_query_fdp_info(struct nvme_ns *ns, struct nvme_ns_info *info)
goto free;
}
head->nr_plids = min(le16_to_cpu(ruhs->nruhsd), S8_MAX - 1);
head->nr_plids = min(le16_to_cpu(ruhs->nruhsd), NVME_MAX_PLIDS);
if (!head->nr_plids)
goto free;