[PATCH 1/2] nvme: check duplicate unique identifiers in order

Bryan Gurney
2025-05-09T17:19:23Z

The identifier check in nvme_subsys_check_duplicate_ids returns an error
if any of the identifiers match; however, this causes problems with
PCI-Express NVMe devices that may otherwise have unique identifiers of
higher precedent (for example, unique NGUIDs, but common EUI64s).

Check for duplicate IDs in order of precedence in the NVMe standard:
UUID, then NGUID, then EUI64, in a way that ensures the highest
priority identifer that exists for the namespace will be checked for
uniquness. If a lower-priority identifier exists and is non-unique, the
higher priority identifier will be unique, and should be used as the
identifier for the namespace.

Suggested-by: John Meneghini <jmeneghi@redhat.com>

Reviewed-by: John Meneghini <jmeneghi@redhat.com>
Signed-off-by: Bryan Gurney <bgurney@redhat.com>
---
drivers/nvme/host/core.c | 32 +++++++++++++++++++++++---------
1 file changed, 23 insertions(+), 9 deletions(-)

diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index eb6ea8acb3cc..49ca29c64ca9 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -3577,15 +3577,29 @@ static int nvme_subsys_check_duplicate_ids(struct nvme_subsystem *subsys,

lockdep_assert_held(&subsys->lock);

- list_for_each_entry(h, &subsys->nsheads, entry) {
- if (has_uuid && uuid_equal(&ids->uuid, &h->ids.uuid))
- return -EINVAL;
- if (has_nguid &&
- memcmp(&ids->nguid, &h->ids.nguid, sizeof(ids->nguid)) == 0)
- return -EINVAL;
- if (has_eui64 &&
- memcmp(&ids->eui64, &h->ids.eui64, sizeof(ids->eui64)) == 0)
- return -EINVAL;
+ if (has_uuid) {
+ list_for_each_entry(h, &subsys->nsheads, entry)
+ if (uuid_equal(&ids->uuid, &h->ids.uuid))
+ return -EINVAL;
+ return 0;
+ }
+
+ if (has_nguid) {
+ list_for_each_entry(h, &subsys->nsheads, entry)
+ if (memcmp(&ids->nguid,
+ &h->ids.nguid,
+ sizeof(ids->nguid)) == 0)
+ return -EINVAL;
+ return 0;
+ }
+
+ if (has_eui64) {
+ list_for_each_entry(h, &subsys->nsheads, entry)
+ if (memcmp(&ids->eui64,
+ &h->ids.eui64,
+ sizeof(ids->eui64)) == 0)
+ return -EINVAL;
+ return 0;
}

return 0;
--
2.49.0