From 3ae8a54a087d54cfd109ab3d844ff4cba54a28d8 Mon Sep 17 00:00:00 2001 From: Klaus Jensen <k.jensen@samsung.com> Date: Wed, 24 May 2023 11:28:34 +0200 Subject: hw/nvme: fix verification of number of ruhis Fix a off-by-one error when verifying the number of reclaim unit handle identifiers specified in fdp.ruhs. To make the fix nicer, move the verification of the fdp.nruh parameter to an earlier point. Fixes: 73064edfb864 ("hw/nvme: flexible data placement emulation") Reviewed-by: Jesper Wendel Devantier <j.devantier@samsung.com> Signed-off-by: Klaus Jensen <k.jensen@samsung.com> --- hw/nvme/ns.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'hw/nvme/ns.c') diff --git a/hw/nvme/ns.c b/hw/nvme/ns.c index 547c0b1543..050fdaf50f 100644 --- a/hw/nvme/ns.c +++ b/hw/nvme/ns.c @@ -438,9 +438,7 @@ static bool nvme_ns_init_fdp(NvmeNamespace *ns, Error **errp) /* parse the placement handle identifiers */ while ((token = qemu_strsep(&p, ";")) != NULL) { - ns->fdp.nphs += 1; - if (ns->fdp.nphs > NVME_FDP_MAXPIDS || - ns->fdp.nphs == endgrp->fdp.nruh) { + if (ns->fdp.nphs++ == endgrp->fdp.nruh) { error_setg(errp, "too many placement handles"); free(r); return false; -- cgit v1.2.3 From 94fa8ca7ee9b6215a5c078f5d424377e5fa61b9c Mon Sep 17 00:00:00 2001 From: Klaus Jensen <k.jensen@samsung.com> Date: Wed, 24 May 2023 11:45:04 +0200 Subject: hw/nvme: verify uniqueness of reclaim unit handle identifiers Verify that a reclaim unit handle identifier is only specified once in fdp.ruhs. Fixes: 73064edfb864 ("hw/nvme: flexible data placement emulation") Reviewed-by: Jesper Wendel Devantier <j.devantier@samsung.com> Signed-off-by: Klaus Jensen <k.jensen@samsung.com> --- hw/nvme/ns.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'hw/nvme/ns.c') diff --git a/hw/nvme/ns.c b/hw/nvme/ns.c index 050fdaf50f..c4ea2033bb 100644 --- a/hw/nvme/ns.c +++ b/hw/nvme/ns.c @@ -453,6 +453,17 @@ static bool nvme_ns_init_fdp(NvmeNamespace *ns, Error **errp) free(r); + /* verify that the ruhids are unique */ + for (unsigned int i = 0; i < ns->fdp.nphs; i++) { + for (unsigned int j = i + 1; j < ns->fdp.nphs; j++) { + if (ruhids[i] == ruhids[j]) { + error_setg(errp, "duplicate reclaim unit handle identifier: %u", + ruhids[i]); + return false; + } + } + } + ph = ns->fdp.phs = g_new(uint16_t, ns->fdp.nphs); ruhid = ruhids; -- cgit v1.2.3 From ce8017736cc82e0250c1bc8e383335822f995510 Mon Sep 17 00:00:00 2001 From: Klaus Jensen <k.jensen@samsung.com> Date: Tue, 14 Feb 2023 10:16:56 +0100 Subject: hw/nvme: add placement handle list ranges Allow the placement handles to be specified as ranges, i.e. `fdp.ruhs=1:3-5` will attempt to assign ruh 1, 3, 4 and 5 to the namespace. Reviewed-by: Jesper Wendel Devantier <j.devantier@samsung.com> Signed-off-by: Klaus Jensen <k.jensen@samsung.com> --- hw/nvme/ns.c | 40 ++++++++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 8 deletions(-) (limited to 'hw/nvme/ns.c') diff --git a/hw/nvme/ns.c b/hw/nvme/ns.c index c4ea2033bb..44aba8f4d9 100644 --- a/hw/nvme/ns.c +++ b/hw/nvme/ns.c @@ -400,8 +400,9 @@ static bool nvme_ns_init_fdp(NvmeNamespace *ns, Error **errp) NvmeRuHandle *ruh; uint8_t lbafi = NVME_ID_NS_FLBAS_INDEX(ns->id_ns.flbas); g_autofree unsigned int *ruhids = NULL; - unsigned int *ruhid; - char *r, *p, *token; + unsigned int n, m, *ruhid; + const char *endptr, *token; + char *r, *p; uint16_t *ph; if (!ns->params.fdp.ruhs) { @@ -438,16 +439,39 @@ static bool nvme_ns_init_fdp(NvmeNamespace *ns, Error **errp) /* parse the placement handle identifiers */ while ((token = qemu_strsep(&p, ";")) != NULL) { - if (ns->fdp.nphs++ == endgrp->fdp.nruh) { - error_setg(errp, "too many placement handles"); + if (qemu_strtoui(token, &endptr, 0, &n) < 0) { + error_setg(errp, "cannot parse reclaim unit handle identifier"); free(r); return false; } - if (qemu_strtoui(token, NULL, 0, ruhid++) < 0) { - error_setg(errp, "cannot parse reclaim unit handle identifier"); - free(r); - return false; + m = n; + + /* parse range */ + if (*endptr == '-') { + token = endptr + 1; + + if (qemu_strtoui(token, NULL, 0, &m) < 0) { + error_setg(errp, "cannot parse reclaim unit handle identifier"); + free(r); + return false; + } + + if (m < n) { + error_setg(errp, "invalid reclaim unit handle identifier range"); + free(r); + return false; + } + } + + for (; n <= m; n++) { + if (ns->fdp.nphs++ == endgrp->fdp.nruh) { + error_setg(errp, "too many placement handles"); + free(r); + return false; + } + + *ruhid++ = n; } } -- cgit v1.2.3