Skip to content

nvme issue #273

Description

@yodayox

think that #272 is incomplete because some( i mean a lot) nvme devices can belong to nvme-subsystem! see >>Werkov/systemd@cef7269
the right patch could be, like i said in the past, the following one:

--- a/src/udev/udev-builtin-path_id.c	2022-11-27 20:07:00.000000000 +0200
+++ b/src/udev/udev-builtin-path_id.c	2022-11-28 08:49:17.518446117 +0200
@@ -614,12 +614,51 @@
         return parent;
 }
 
+static int find_real_nvme_parent(struct udev_device *dev, struct udev_device **ret) {
+        _cleanup_free_ struct udev_device *nvme = NULL;
+        const char *sysname, *end;
+        struct udev *udev = udev_device_get_udev(dev);
+
+        /* If the device belongs to "nvme-subsystem" (not to be confused with "nvme"), which happens when
+         * NVMe multipathing is enabled in the kernel (/sys/module/nvme_core/parameters/multipath is Y),
+         * then the syspath is something like the following:
+         *   /sys/devices/virtual/nvme-subsystem/nvme-subsys0/nvme0n1
+         * Hence, we need to find the 'real parent' in "nvme" subsystem, e.g,
+         *   /sys/devices/pci0000:00/0000:00:1c.4/0000:3c:00.0/nvme/nvme0 */
+
+        assert(dev);
+        assert(ret);
+
+        sysname = udev_device_get_sysname(dev);
+        if (sysname  ==  NULL)
+                return -1;
+
+        /* The sysname format of nvme block device is nvme%d[c%d]n%d[p%d], e.g. nvme0n1p2 or nvme0c1n2.
+         * (Note, nvme device with 'c' can be ignored, as they are hidden. )
+         * The sysname format of nvme subsystem device is nvme%d.
+         * See nvme_alloc_ns() and nvme_init_ctrl() in drivers/nvme/host/core.c for more details. */
+        end = startswith(sysname, "nvme");
+        if (!end)
+                return -ENXIO;
+
+        end += strspn(end, "0123456789");
+        sysname = strndupa(sysname, end - sysname);
+
+        nvme = udev_device_new_from_subsystem_sysname(udev, "nvme", sysname);
+        if (nvme == NULL)
+                return -1;
+
+        *ret = TAKE_PTR(nvme);
+        return 0;
+}
+
 static int builtin_path_id(struct udev_device *dev, int argc __attribute__((unused)), char *argv[] __attribute__((unused)), bool test) {
         struct udev_device *parent;
         char *path = NULL;
         bool supported_transport = false;
         bool supported_parent = false;
         char *compat_path = NULL;
+        _cleanup_free_ struct udev_device *dev_other_branch = NULL;
         
         /* S390 ccw bus */
         parent = udev_device_get_parent_with_subsystem_devtype(dev, "ccw", NULL);
@@ -685,6 +724,36 @@
                         parent = skip_subsystem(parent, "scm");
                         supported_transport = true;
                         supported_parent = true;
+                } else if (streq(subsys, "nvme") || streq(subsys, "nvme-subsystem")) {
+                        const char *nsid;
+                        int r;
+                        
+                        nsid = udev_device_get_sysattr_value(dev, "nsid");
+                        if (nsid != NULL) {
+                                path_prepend(&path, "nvme-%s", nsid);
+                                if (compat_path)
+                                        path_prepend(&compat_path, "nvme-%s", nsid);
+
+                                if (streq(subsys, "nvme-subsystem")) {
+                                        r = find_real_nvme_parent(dev, &dev_other_branch);
+                                        if (r < 0)
+                                                return r;
+
+                                        parent = dev_other_branch;
+                                }
+
+                                parent = skip_subsystem(parent, "nvme");
+                                supported_parent = true;
+                                supported_transport = true;
+                        }
+                } else if (streq(subsys, "spi")) {
+                        const char *sysnum;
+                        
+                        sysnum = udev_device_get_sysname(parent);
+                        if (sysnum !=NULL) {
+                                path_prepend(&path, "cs-%s", sysnum);
+                                parent = skip_subsystem(parent, "spi");
+                        }
                 }
 
                 parent = udev_device_get_parent(parent);

--- a/src/udev/udev.h	2022-06-14 02:44:42.000000000 +0300
+++ b/src/udev/udev.h	2022-11-28 11:51:02.744444816 +0200
@@ -212,3 +212,11 @@
 extern const struct udevadm_cmd udevadm_hwdb;
 extern const struct udevadm_cmd udevadm_test;
 extern const struct udevadm_cmd udevadm_test_builtin;
+
+#define TAKE_PTR(ptr)                           \
+        ({                                      \
+                typeof(ptr) *_pptr_ = &(ptr);   \
+                typeof(ptr) _ptr_ = *_pptr_;    \
+                *_pptr_ = NULL;                 \
+                _ptr_;                          \
+        })

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions