From 53cdaeab2e30e0cb849a74b94f93729ad98946b1 Mon Sep 17 00:00:00 2001 From: Guixin Liu Date: Tue, 4 Aug 2026 10:19:01 +0800 Subject: [PATCH] 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 Signed-off-by: Guixin Liu Reviewed-by: Kanchan Joshi Reviewed-by: Nilay Shroff Reviewed-by: Christoph Hellwig Signed-off-by: Keith Busch --- drivers/nvme/host/core.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index 975181a74fae..a59abd770aff 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -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;