eudev-project / eudev

Repository for eudev development
GNU General Public License v2.0
521 stars 145 forks source link

nvme issue #273

Open yodayox opened 7 months ago

yodayox commented 7 months ago

think that https://github.com/eudev-project/eudev/pull/272 is incomplete because some( i mean a lot) nvme devices can belong to nvme-subsystem! see >>https://github.com/Werkov/systemd/commit/cef726986b7117dec3e827a3c5c09d2bbdc4692a 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_;                          \
+        })