summaryrefslogtreecommitdiff
path: root/0005-nvme-Fix-namespace-identifiers.patch
diff options
context:
space:
mode:
Diffstat (limited to '0005-nvme-Fix-namespace-identifiers.patch')
-rw-r--r--0005-nvme-Fix-namespace-identifiers.patch506
1 files changed, 506 insertions, 0 deletions
diff --git a/0005-nvme-Fix-namespace-identifiers.patch b/0005-nvme-Fix-namespace-identifiers.patch
new file mode 100644
index 0000000..7334ff1
--- /dev/null
+++ b/0005-nvme-Fix-namespace-identifiers.patch
@@ -0,0 +1,506 @@
+From b25fd9caca9b2fb34e5a4d7d4bee0031e4758d0a Mon Sep 17 00:00:00 2001
+From: Tomas Bzatek <tbzatek@redhat.com>
+Date: Thu, 22 Sep 2022 16:31:28 +0200
+Subject: [PATCH 1/5] nvme: Avoid sending NVME_IDENTIFY_CNS_NS_DESC_LIST on
+ older devices
+
+Turned out this Identify feature was introduced only with the NVMe 1.3
+specification. To find out device supported NVMe revision an extra
+Identify Controller call is needed.
+---
+ src/plugins/nvme/nvme-info.c | 14 +++++++++++---
+ 1 file changed, 11 insertions(+), 3 deletions(-)
+
+diff --git a/src/plugins/nvme/nvme-info.c b/src/plugins/nvme/nvme-info.c
+index fdd90459..112b4054 100644
+--- a/src/plugins/nvme/nvme-info.c
++++ b/src/plugins/nvme/nvme-info.c
+@@ -431,7 +431,7 @@ BDNVMEControllerInfo * bd_nvme_get_controller_info (const gchar *device, GError
+ if (fd < 0)
+ return NULL;
+
+- /* send the NVME_IDENTIFY_CNS_NS + NVME_IDENTIFY_CNS_CTRL ioctl */
++ /* send the NVME_IDENTIFY_CNS_CTRL ioctl */
+ ret = nvme_identify_ctrl (fd, &ctrl_id);
+ if (ret != 0) {
+ _nvme_status_to_error (ret, FALSE, error);
+@@ -539,9 +539,11 @@ BDNVMEControllerInfo * bd_nvme_get_controller_info (const gchar *device, GError
+ */
+ BDNVMENamespaceInfo *bd_nvme_get_namespace_info (const gchar *device, GError **error) {
+ int ret;
+- int ret_desc;
++ int ret_ctrl;
++ int ret_desc = -1;
+ int fd;
+ __u32 nsid = 0;
++ struct nvme_id_ctrl ctrl_id = ZERO_INIT;
+ struct nvme_id_ns ns_info = ZERO_INIT;
+ uint8_t desc[NVME_IDENTIFY_DATA_SIZE] = ZERO_INIT;
+ guint8 flbas;
+@@ -565,7 +567,6 @@ BDNVMENamespaceInfo *bd_nvme_get_namespace_info (const gchar *device, GError **e
+ }
+
+ /* send the NVME_IDENTIFY_CNS_NS ioctl */
+- ret_desc = nvme_identify_ns_descs (fd, nsid, (struct nvme_ns_id_desc *) &desc);
+ ret = nvme_identify_ns (fd, nsid, &ns_info);
+ if (ret != 0) {
+ _nvme_status_to_error (ret, FALSE, error);
+@@ -573,6 +574,13 @@ BDNVMENamespaceInfo *bd_nvme_get_namespace_info (const gchar *device, GError **e
+ close (fd);
+ return NULL;
+ }
++
++ /* send the NVME_IDENTIFY_CNS_CTRL ioctl */
++ ret_ctrl = nvme_identify_ctrl (fd, &ctrl_id);
++
++ /* send the NVME_IDENTIFY_CNS_NS_DESC_LIST ioctl, NVMe 1.3 */
++ if (ret_ctrl == 0 && GUINT32_FROM_LE (ctrl_id.ver) >= 0x10300)
++ ret_desc = nvme_identify_ns_descs (fd, nsid, (struct nvme_ns_id_desc *) &desc);
+ close (fd);
+
+ info = g_new0 (BDNVMENamespaceInfo, 1);
+--
+2.39.0
+
+
+From e6f7d0c4562623b03df96dc6b89ab00d8e4d6b90 Mon Sep 17 00:00:00 2001
+From: Tomas Bzatek <tbzatek@redhat.com>
+Date: Thu, 22 Sep 2022 16:56:26 +0200
+Subject: [PATCH 2/5] nvme: Add BD_NVME_NS_FEAT_ROTATIONAL
+
+A NVMe 2.0 feature indicating rotational medium on a namespace level.
+Further information can be found in the Rotational Media Information Log
+page (Log Identifier 16h) that is not implemented in libblockdev yet.
+---
+ src/lib/plugin_apis/nvme.api | 2 ++
+ src/plugins/nvme/nvme-info.c | 10 ++++++++++
+ src/plugins/nvme/nvme.h | 2 ++
+ tests/nvme_test.py | 1 +
+ 4 files changed, 15 insertions(+)
+
+diff --git a/src/lib/plugin_apis/nvme.api b/src/lib/plugin_apis/nvme.api
+index 79247a01..7bc2cf9e 100644
+--- a/src/lib/plugin_apis/nvme.api
++++ b/src/lib/plugin_apis/nvme.api
+@@ -317,12 +317,14 @@ GType bd_nvme_lba_format_get_type () {
+ * in the NVM subsystem concurrently.
+ * @BD_NVME_NS_FEAT_FORMAT_PROGRESS: indicates the capability to report the percentage of the namespace
+ * that remains to be formatted.
++ * @BD_NVME_NS_FEAT_ROTATIONAL: indicates a rotational medium.
+ */
+ /* BpG-skip-end */
+ typedef enum {
+ BD_NVME_NS_FEAT_THIN = 1 << 0,
+ BD_NVME_NS_FEAT_MULTIPATH_SHARED = 1 << 1,
+ BD_NVME_NS_FEAT_FORMAT_PROGRESS = 1 << 2,
++ BD_NVME_NS_FEAT_ROTATIONAL = 1 << 3,
+ } BDNVMENamespaceFeature;
+
+ #define BD_NVME_TYPE_NAMESPACE_INFO (bd_nvme_namespace_info_get_type ())
+diff --git a/src/plugins/nvme/nvme-info.c b/src/plugins/nvme/nvme-info.c
+index 112b4054..c574a6f3 100644
+--- a/src/plugins/nvme/nvme-info.c
++++ b/src/plugins/nvme/nvme-info.c
+@@ -541,10 +541,12 @@ BDNVMENamespaceInfo *bd_nvme_get_namespace_info (const gchar *device, GError **e
+ int ret;
+ int ret_ctrl;
+ int ret_desc = -1;
++ int ret_ns_ind = -1;
+ int fd;
+ __u32 nsid = 0;
+ struct nvme_id_ctrl ctrl_id = ZERO_INIT;
+ struct nvme_id_ns ns_info = ZERO_INIT;
++ struct nvme_id_independent_id_ns ns_info_ind = ZERO_INIT;
+ uint8_t desc[NVME_IDENTIFY_DATA_SIZE] = ZERO_INIT;
+ guint8 flbas;
+ guint i;
+@@ -581,6 +583,10 @@ BDNVMENamespaceInfo *bd_nvme_get_namespace_info (const gchar *device, GError **e
+ /* send the NVME_IDENTIFY_CNS_NS_DESC_LIST ioctl, NVMe 1.3 */
+ if (ret_ctrl == 0 && GUINT32_FROM_LE (ctrl_id.ver) >= 0x10300)
+ ret_desc = nvme_identify_ns_descs (fd, nsid, (struct nvme_ns_id_desc *) &desc);
++
++ /* send the NVME_IDENTIFY_CNS_CSI_INDEPENDENT_ID_NS ioctl, NVMe 2.0 */
++ if (ret_ctrl == 0 && GUINT32_FROM_LE (ctrl_id.ver) >= 0x20000)
++ ret_ns_ind = nvme_identify_independent_identify_ns (fd, nsid, &ns_info_ind);
+ close (fd);
+
+ info = g_new0 (BDNVMENamespaceInfo, 1);
+@@ -627,6 +633,10 @@ BDNVMENamespaceInfo *bd_nvme_get_namespace_info (const gchar *device, GError **e
+ }
+ }
+ }
++ if (ret_ns_ind == 0) {
++ if ((ns_info_ind.nsfeat & 1 << 4) == 1 << 4)
++ info->features |= BD_NVME_NS_FEAT_ROTATIONAL;
++ }
+
+ /* translate the LBA Format array */
+ ptr_array = g_ptr_array_new ();
+diff --git a/src/plugins/nvme/nvme.h b/src/plugins/nvme/nvme.h
+index a7d30d79..ad456a82 100644
+--- a/src/plugins/nvme/nvme.h
++++ b/src/plugins/nvme/nvme.h
+@@ -202,11 +202,13 @@ typedef struct BDNVMELBAFormat {
+ * in the NVM subsystem concurrently.
+ * @BD_NVME_NS_FEAT_FORMAT_PROGRESS: indicates the capability to report the percentage of the namespace
+ * that remains to be formatted.
++ * @BD_NVME_NS_FEAT_ROTATIONAL: indicates a rotational medium.
+ */
+ typedef enum {
+ BD_NVME_NS_FEAT_THIN = 1 << 0,
+ BD_NVME_NS_FEAT_MULTIPATH_SHARED = 1 << 1,
+ BD_NVME_NS_FEAT_FORMAT_PROGRESS = 1 << 2,
++ BD_NVME_NS_FEAT_ROTATIONAL = 1 << 3,
+ } BDNVMENamespaceFeature;
+
+ /**
+diff --git a/tests/nvme_test.py b/tests/nvme_test.py
+index a46f7422..f205e539 100644
+--- a/tests/nvme_test.py
++++ b/tests/nvme_test.py
+@@ -73,6 +73,7 @@ class NVMeTestCase(NVMeTest):
+ self.assertFalse(info.features & BlockDev.NVMENamespaceFeature.THIN)
+ self.assertTrue (info.features & BlockDev.NVMENamespaceFeature.MULTIPATH_SHARED)
+ self.assertFalse(info.features & BlockDev.NVMENamespaceFeature.FORMAT_PROGRESS)
++ self.assertFalse(info.features & BlockDev.NVMENamespaceFeature.ROTATIONAL)
+ self.assertEqual(info.eui64, "0000000000000000")
+ self.assertEqual(info.format_progress_remaining, 0)
+ self.assertEqual(len(info.lba_formats), 1)
+--
+2.39.0
+
+
+From 4ff0df937dcd357623e7b7d960c08c476b1deffb Mon Sep 17 00:00:00 2001
+From: Tomas Bzatek <tbzatek@redhat.com>
+Date: Fri, 9 Dec 2022 16:13:43 +0100
+Subject: [PATCH 3/5] nvme: Fix namespace identifiers
+
+Use Namespace Identification Descriptor list (CNS 03h) data when available
+and NVM Command Set Identify Namespace Data Structure (CNS 00h) as a fallback.
+
+Also, if the CNS 00h EUI64 or NGUID fields equal to zero, return NULL
+instead of zeroes:
+ "If the controller is not able to provide a ... identifier in this field,
+ then this field shall be cleared to 0h."
+---
+ src/plugins/nvme/nvme-info.c | 26 +++++++++++++++++++-------
+ tests/nvme_test.py | 2 +-
+ 2 files changed, 20 insertions(+), 8 deletions(-)
+
+diff --git a/src/plugins/nvme/nvme-info.c b/src/plugins/nvme/nvme-info.c
+index c574a6f3..ac189abe 100644
+--- a/src/plugins/nvme/nvme-info.c
++++ b/src/plugins/nvme/nvme-info.c
+@@ -603,12 +603,7 @@ BDNVMENamespaceInfo *bd_nvme_get_namespace_info (const gchar *device, GError **e
+ info->format_progress_remaining = ns_info.fpi & NVME_NS_FPI_REMAINING;
+ /* TODO: what the ns_info.nvmcap really stands for? */
+ info->write_protected = (ns_info.nsattr & NVME_NS_NSATTR_WRITE_PROTECTED) == NVME_NS_NSATTR_WRITE_PROTECTED;
+- info->nguid = g_malloc0 (sizeof (ns_info.nguid) * 2 + 1);
+- for (i = 0; i < G_N_ELEMENTS (ns_info.nguid); i++)
+- snprintf (info->nguid + i * 2, 3, "%02x", ns_info.nguid[i]);
+- info->eui64 = g_malloc0 (sizeof (ns_info.eui64) * 2 + 1);
+- for (i = 0; i < G_N_ELEMENTS (ns_info.eui64); i++)
+- snprintf (info->eui64 + i * 2, 3, "%02x", ns_info.eui64[i]);
++
+ if (ret_desc == 0) {
+ for (i = 0; i < NVME_IDENTIFY_DATA_SIZE; i += len) {
+ struct nvme_ns_id_desc *d = (void *) desc + i;
+@@ -620,8 +615,14 @@ BDNVMENamespaceInfo *bd_nvme_get_namespace_info (const gchar *device, GError **e
+
+ switch (d->nidt) {
+ case NVME_NIDT_EUI64:
++ info->eui64 = g_malloc0 (d->nidl * 2 + 1);
++ for (i = 0; i < d->nidl; i++)
++ snprintf (info->eui64 + i * 2, 3, "%02x", d->nid[i]);
++ break;
+ case NVME_NIDT_NGUID:
+- /* already have these from nvme_identify_ns() */
++ info->nguid = g_malloc0 (d->nidl * 2 + 1);
++ for (i = 0; i < d->nidl; i++)
++ snprintf (info->nguid + i * 2, 3, "%02x", d->nid[i]);
+ break;
+ case NVME_NIDT_UUID:
+ uuid_unparse (d->nid, uuid_buf);
+@@ -633,6 +634,17 @@ BDNVMENamespaceInfo *bd_nvme_get_namespace_info (const gchar *device, GError **e
+ }
+ }
+ }
++
++ if (info->nguid == NULL && ns_info.nguid[G_N_ELEMENTS (ns_info.nguid) - 1] > 0) {
++ info->nguid = g_malloc0 (sizeof (ns_info.nguid) * 2 + 1);
++ for (i = 0; i < G_N_ELEMENTS (ns_info.nguid); i++)
++ snprintf (info->nguid + i * 2, 3, "%02x", ns_info.nguid[i]);
++ }
++ if (info->eui64 == NULL && ns_info.eui64[G_N_ELEMENTS (ns_info.eui64) - 1] > 0) {
++ info->eui64 = g_malloc0 (sizeof (ns_info.eui64) * 2 + 1);
++ for (i = 0; i < G_N_ELEMENTS (ns_info.eui64); i++)
++ snprintf (info->eui64 + i * 2, 3, "%02x", ns_info.eui64[i]);
++ }
+ if (ret_ns_ind == 0) {
+ if ((ns_info_ind.nsfeat & 1 << 4) == 1 << 4)
+ info->features |= BD_NVME_NS_FEAT_ROTATIONAL;
+diff --git a/tests/nvme_test.py b/tests/nvme_test.py
+index f205e539..a1822be6 100644
+--- a/tests/nvme_test.py
++++ b/tests/nvme_test.py
+@@ -74,7 +74,7 @@ class NVMeTestCase(NVMeTest):
+ self.assertTrue (info.features & BlockDev.NVMENamespaceFeature.MULTIPATH_SHARED)
+ self.assertFalse(info.features & BlockDev.NVMENamespaceFeature.FORMAT_PROGRESS)
+ self.assertFalse(info.features & BlockDev.NVMENamespaceFeature.ROTATIONAL)
+- self.assertEqual(info.eui64, "0000000000000000")
++ self.assertIsNone(info.eui64)
+ self.assertEqual(info.format_progress_remaining, 0)
+ self.assertEqual(len(info.lba_formats), 1)
+ self.assertGreater(len(info.nguid), 0)
+--
+2.39.0
+
+
+From cdbb9a37a19d3f388910f68c4c384bafae8901ae Mon Sep 17 00:00:00 2001
+From: Tomas Bzatek <tbzatek@redhat.com>
+Date: Wed, 11 Jan 2023 18:19:36 +0100
+Subject: [PATCH 4/5] nvme: Use libnvme-1.2's nvme_uuid_to_string()
+
+This also bumps libnvme dependency to 1.2
+---
+ configure.ac | 5 +----
+ src/plugins/nvme/Makefile.am | 4 ++--
+ src/plugins/nvme/nvme-error.c | 3 ---
+ src/plugins/nvme/nvme-fabrics.c | 1 -
+ src/plugins/nvme/nvme-info.c | 17 ++++++++++-------
+ src/plugins/nvme/nvme-op.c | 1 -
+ src/plugins/nvme/nvme.c | 1 -
+ 7 files changed, 13 insertions(+), 19 deletions(-)
+
+diff --git a/configure.ac b/configure.ac
+index ec789c91..fbd70473 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -281,10 +281,7 @@ AS_IF([test "x$with_nvdimm" != "xno"],
+ [])
+
+ AS_IF([test "x$with_nvme" != "xno"],
+- [LIBBLOCKDEV_PKG_CHECK_MODULES([NVME], [libnvme >= 1.0])
+- AS_IF([$PKG_CONFIG --atleast-version=1.1 libnvme],
+- [AC_DEFINE([HAVE_LIBNVME_1_1])], [])
+- ],
++ [LIBBLOCKDEV_PKG_CHECK_MODULES([NVME], [libnvme >= 1.2])],
+ [])
+
+ AS_IF([test "x$with_vdo" != "xno"],
+diff --git a/src/plugins/nvme/Makefile.am b/src/plugins/nvme/Makefile.am
+index b4a10ce0..a8a856d4 100644
+--- a/src/plugins/nvme/Makefile.am
++++ b/src/plugins/nvme/Makefile.am
+@@ -2,8 +2,8 @@ AUTOMAKE_OPTIONS = subdir-objects
+
+ lib_LTLIBRARIES = libbd_nvme.la
+
+-libbd_nvme_la_CFLAGS = $(GLIB_CFLAGS) $(GIO_CFLAGS) $(UUID_CFLAGS) $(NVME_CFLAGS) -Wall -Wextra -Werror
+-libbd_nvme_la_LIBADD = ${builddir}/../../utils/libbd_utils.la $(GLIB_LIBS) $(GIO_LIBS) $(UUID_LIBS) $(NVME_LIBS)
++libbd_nvme_la_CFLAGS = $(GLIB_CFLAGS) $(GIO_CFLAGS) $(NVME_CFLAGS) -Wall -Wextra -Werror
++libbd_nvme_la_LIBADD = ${builddir}/../../utils/libbd_utils.la $(GLIB_LIBS) $(GIO_LIBS) $(NVME_LIBS)
+ libbd_nvme_la_LDFLAGS = -L${srcdir}/../../utils/ -version-info 2:0:0 -Wl,--no-undefined
+ libbd_nvme_la_CPPFLAGS = -I${builddir}/../../../include/ -I${srcdir}/../ -I. -DPACKAGE_SYSCONF_DIR=\""$(sysconfdir)"\"
+
+diff --git a/src/plugins/nvme/nvme-error.c b/src/plugins/nvme/nvme-error.c
+index 86f0d6a3..cb95a46d 100644
+--- a/src/plugins/nvme/nvme-error.c
++++ b/src/plugins/nvme/nvme-error.c
+@@ -28,7 +28,6 @@
+ #include <malloc.h>
+
+ #include <libnvme.h>
+-#include <uuid/uuid.h>
+
+ #include <blockdev/utils.h>
+ #include <check_deps.h>
+@@ -123,7 +122,6 @@ void _nvme_fabrics_errno_to_gerror (int result, int _errno, GError **error)
+ case ENVME_CONNECT_LOOKUP_SUBSYS:
+ code = BD_NVME_ERROR_CONNECT;
+ break;
+-#ifdef HAVE_LIBNVME_1_1
+ case ENVME_CONNECT_ALREADY:
+ code = BD_NVME_ERROR_CONNECT_ALREADY;
+ break;
+@@ -139,7 +137,6 @@ void _nvme_fabrics_errno_to_gerror (int result, int _errno, GError **error)
+ case ENVME_CONNECT_OPNOTSUPP:
+ code = BD_NVME_ERROR_CONNECT_OPNOTSUPP;
+ break;
+-#endif
+ default:
+ code = BD_NVME_ERROR_CONNECT;
+ }
+diff --git a/src/plugins/nvme/nvme-fabrics.c b/src/plugins/nvme/nvme-fabrics.c
+index 20ed57f5..bba7392d 100644
+--- a/src/plugins/nvme/nvme-fabrics.c
++++ b/src/plugins/nvme/nvme-fabrics.c
+@@ -30,7 +30,6 @@
+ #include <glib/gstdio.h>
+
+ #include <libnvme.h>
+-#include <uuid/uuid.h>
+
+ #include <blockdev/utils.h>
+ #include <check_deps.h>
+diff --git a/src/plugins/nvme/nvme-info.c b/src/plugins/nvme/nvme-info.c
+index ac189abe..18719d51 100644
+--- a/src/plugins/nvme/nvme-info.c
++++ b/src/plugins/nvme/nvme-info.c
+@@ -28,7 +28,6 @@
+ #include <malloc.h>
+
+ #include <libnvme.h>
+-#include <uuid/uuid.h>
+
+ #include <blockdev/utils.h>
+ #include <check_deps.h>
+@@ -408,6 +407,14 @@ static gchar *decode_nvme_rev (guint32 ver) {
+ return g_strdup_printf ("%u.%u.%u", mjr, mnr, ter);
+ }
+
++static gchar *_uuid_to_str (unsigned char uuid[NVME_UUID_LEN]) {
++ gchar uuid_buf[NVME_UUID_LEN_STRING] = ZERO_INIT;
++
++ if (nvme_uuid_to_string (uuid, uuid_buf) == 0)
++ return g_strdup (uuid_buf);
++ return NULL;
++}
++
+ /**
+ * bd_nvme_get_controller_info:
+ * @device: a NVMe controller device (e.g. `/dev/nvme0`)
+@@ -461,9 +468,7 @@ BDNVMEControllerInfo * bd_nvme_get_controller_info (const gchar *device, GError
+ info->pci_vendor_id = GUINT16_FROM_LE (ctrl_id.vid);
+ info->pci_subsys_vendor_id = GUINT16_FROM_LE (ctrl_id.ssvid);
+ info->ctrl_id = GUINT16_FROM_LE (ctrl_id.cntlid);
+- /* TODO: decode fguid as 128-bit hex string? */
+- info->fguid = g_strdup_printf ("%-.*s", (int) sizeof (ctrl_id.fguid), ctrl_id.fguid);
+- g_strstrip (info->fguid);
++ info->fguid = _uuid_to_str (ctrl_id.fguid);
+ info->model_number = g_strndup (ctrl_id.mn, sizeof (ctrl_id.mn));
+ g_strstrip (info->model_number);
+ info->serial_number = g_strndup (ctrl_id.sn, sizeof (ctrl_id.sn));
+@@ -607,7 +612,6 @@ BDNVMENamespaceInfo *bd_nvme_get_namespace_info (const gchar *device, GError **e
+ if (ret_desc == 0) {
+ for (i = 0; i < NVME_IDENTIFY_DATA_SIZE; i += len) {
+ struct nvme_ns_id_desc *d = (void *) desc + i;
+- gchar uuid_buf[37] = ZERO_INIT;
+
+ if (!d->nidl)
+ break;
+@@ -625,8 +629,7 @@ BDNVMENamespaceInfo *bd_nvme_get_namespace_info (const gchar *device, GError **e
+ snprintf (info->nguid + i * 2, 3, "%02x", d->nid[i]);
+ break;
+ case NVME_NIDT_UUID:
+- uuid_unparse (d->nid, uuid_buf);
+- info->uuid = g_strdup (uuid_buf);
++ info->uuid = _uuid_to_str (d->nid);
+ break;
+ case NVME_NIDT_CSI:
+ /* unused */
+diff --git a/src/plugins/nvme/nvme-op.c b/src/plugins/nvme/nvme-op.c
+index 4568c453..c9e92697 100644
+--- a/src/plugins/nvme/nvme-op.c
++++ b/src/plugins/nvme/nvme-op.c
+@@ -29,7 +29,6 @@
+ #include <linux/fs.h>
+
+ #include <libnvme.h>
+-#include <uuid/uuid.h>
+
+ #include <blockdev/utils.h>
+ #include <check_deps.h>
+diff --git a/src/plugins/nvme/nvme.c b/src/plugins/nvme/nvme.c
+index 00f2f76e..4a32ac4e 100644
+--- a/src/plugins/nvme/nvme.c
++++ b/src/plugins/nvme/nvme.c
+@@ -28,7 +28,6 @@
+ #include <malloc.h>
+
+ #include <libnvme.h>
+-#include <uuid/uuid.h>
+
+ #include <blockdev/utils.h>
+ #include <check_deps.h>
+--
+2.39.0
+
+
+From 64263599ec39b6b0f20d8e16c1169afcf66f5d9a Mon Sep 17 00:00:00 2001
+From: Tomas Bzatek <tbzatek@redhat.com>
+Date: Thu, 12 Jan 2023 16:01:28 +0100
+Subject: [PATCH 5/5] nvme: Fix zeroed struct fields detection
+
+As often stated in the NVMe specification, fields of features that
+are either not implemented or not valid are typically cleared to zero (0h).
+---
+ src/plugins/nvme/nvme-info.c | 20 +++++++++++++++-----
+ tests/nvme_test.py | 2 +-
+ 2 files changed, 16 insertions(+), 6 deletions(-)
+
+diff --git a/src/plugins/nvme/nvme-info.c b/src/plugins/nvme/nvme-info.c
+index 18719d51..85f94a32 100644
+--- a/src/plugins/nvme/nvme-info.c
++++ b/src/plugins/nvme/nvme-info.c
+@@ -415,6 +415,15 @@ static gchar *_uuid_to_str (unsigned char uuid[NVME_UUID_LEN]) {
+ return NULL;
+ }
+
++static gboolean _nvme_a_is_zero (const __u8 a[], int len) {
++ int i;
++
++ for (i = 0; i < len; i++)
++ if (a[i] > 0)
++ return FALSE;
++ return TRUE;
++}
++
+ /**
+ * bd_nvme_get_controller_info:
+ * @device: a NVMe controller device (e.g. `/dev/nvme0`)
+@@ -468,7 +477,8 @@ BDNVMEControllerInfo * bd_nvme_get_controller_info (const gchar *device, GError
+ info->pci_vendor_id = GUINT16_FROM_LE (ctrl_id.vid);
+ info->pci_subsys_vendor_id = GUINT16_FROM_LE (ctrl_id.ssvid);
+ info->ctrl_id = GUINT16_FROM_LE (ctrl_id.cntlid);
+- info->fguid = _uuid_to_str (ctrl_id.fguid);
++ if (!_nvme_a_is_zero (ctrl_id.fguid, sizeof (ctrl_id.fguid)))
++ info->fguid = _uuid_to_str (ctrl_id.fguid);
+ info->model_number = g_strndup (ctrl_id.mn, sizeof (ctrl_id.mn));
+ g_strstrip (info->model_number);
+ info->serial_number = g_strndup (ctrl_id.sn, sizeof (ctrl_id.sn));
+@@ -638,14 +648,14 @@ BDNVMENamespaceInfo *bd_nvme_get_namespace_info (const gchar *device, GError **e
+ }
+ }
+
+- if (info->nguid == NULL && ns_info.nguid[G_N_ELEMENTS (ns_info.nguid) - 1] > 0) {
++ if (info->nguid == NULL && !_nvme_a_is_zero (ns_info.nguid, sizeof (ns_info.nguid))) {
+ info->nguid = g_malloc0 (sizeof (ns_info.nguid) * 2 + 1);
+- for (i = 0; i < G_N_ELEMENTS (ns_info.nguid); i++)
++ for (i = 0; i < sizeof (ns_info.nguid); i++)
+ snprintf (info->nguid + i * 2, 3, "%02x", ns_info.nguid[i]);
+ }
+- if (info->eui64 == NULL && ns_info.eui64[G_N_ELEMENTS (ns_info.eui64) - 1] > 0) {
++ if (info->eui64 == NULL && !_nvme_a_is_zero (ns_info.eui64, sizeof (ns_info.eui64))) {
+ info->eui64 = g_malloc0 (sizeof (ns_info.eui64) * 2 + 1);
+- for (i = 0; i < G_N_ELEMENTS (ns_info.eui64); i++)
++ for (i = 0; i < sizeof (ns_info.eui64); i++)
+ snprintf (info->eui64 + i * 2, 3, "%02x", ns_info.eui64[i]);
+ }
+ if (ret_ns_ind == 0) {
+diff --git a/tests/nvme_test.py b/tests/nvme_test.py
+index a1822be6..a1494d9a 100644
+--- a/tests/nvme_test.py
++++ b/tests/nvme_test.py
+@@ -116,7 +116,7 @@ class NVMeTestCase(NVMeTest):
+ self.assertFalse(info.features & BlockDev.NVMEControllerFeature.ENCLOSURE)
+ self.assertFalse(info.features & BlockDev.NVMEControllerFeature.MGMT_PCIE)
+ self.assertFalse(info.features & BlockDev.NVMEControllerFeature.MGMT_SMBUS)
+- self.assertEqual(info.fguid, "")
++ self.assertIsNone(info.fguid)
+ self.assertEqual(info.pci_vendor_id, 0)
+ self.assertEqual(info.pci_subsys_vendor_id, 0)
+ self.assertIn("Linux", info.model_number)
+--
+2.39.0
+