]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
imsm: nvme multipath support
authorBlazej Kucman <blazej.kucman@intel.com>
Fri, 12 Mar 2021 09:30:16 +0000 (10:30 +0100)
committerJes Sorensen <jsorensen@fb.com>
Tue, 16 Mar 2021 20:22:39 +0000 (16:22 -0400)
Add support for nvme devices which are represented
via nvme-subsystem.
Print warning when multi-path disk is added to RAID.

Signed-off-by: Oleksandr Shchirskyi <oleksandr.shchirskyi@intel.com>
Signed-off-by: Blazej Kucman <blazej.kucman@intel.com>
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Signed-off-by: Jes Sorensen <jsorensen@fb.com>
platform-intel.c
platform-intel.h
super-intel.c

index f1f6d4cd8fc3461946e2c895d3dd256f7f0c9485..0e1ec3d546a049dac791dbeb5636632a4f25bb78 100644 (file)
@@ -30,6 +30,8 @@
 #include <sys/stat.h>
 #include <limits.h>
 
+#define NVME_SUBSYS_PATH "/sys/devices/virtual/nvme-subsystem/"
+
 static int devpath_to_ll(const char *dev_path, const char *entry,
                         unsigned long long *val);
 
@@ -668,12 +670,63 @@ const struct imsm_orom *find_imsm_capability(struct sys_dev *hba)
        return NULL;
 }
 
+/* Check whether the nvme device is represented by nvme subsytem,
+ * if yes virtual path should be changed to hardware device path,
+ * to allow IMSM capabilities detection.
+ * Returns:
+ *     hardware path to device - if the device is represented via
+ *             nvme virtual subsytem
+ *     NULL - if the device is not represented via nvme virtual subsytem
+ */
+char *get_nvme_multipath_dev_hw_path(const char *dev_path)
+{
+       DIR *dir;
+       struct dirent *ent;
+       char *rp = NULL;
+
+       if (strncmp(dev_path, NVME_SUBSYS_PATH, strlen(NVME_SUBSYS_PATH)) != 0)
+               return NULL;
+
+       dir = opendir(dev_path);
+       if (!dir)
+               return NULL;
+
+       for (ent = readdir(dir); ent; ent = readdir(dir)) {
+               char buf[strlen(dev_path) + strlen(ent->d_name) + 1];
+
+               /* Check if dir is a controller, ignore namespaces*/
+               if (!(strncmp(ent->d_name, "nvme", 4) == 0) ||
+                   (strrchr(ent->d_name, 'n') != &ent->d_name[0]))
+                       continue;
+
+               sprintf(buf, "%s/%s", dev_path, ent->d_name);
+               rp = realpath(buf, NULL);
+               break;
+       }
+
+       closedir(dir);
+       return rp;
+}
+
 char *devt_to_devpath(dev_t dev)
 {
        char device[46];
+       char *rp;
+       char *buf;
 
        sprintf(device, "/sys/dev/block/%d:%d/device", major(dev), minor(dev));
-       return realpath(device, NULL);
+
+       rp = realpath(device, NULL);
+       if (!rp)
+               return NULL;
+
+       buf = get_nvme_multipath_dev_hw_path(rp);
+       if (buf) {
+               free(rp);
+               return buf;
+       }
+
+       return rp;
 }
 
 char *diskfd_to_devpath(int fd)
@@ -797,3 +850,27 @@ int imsm_is_nvme_supported(int disk_fd, int verbose)
        }
        return 1;
 }
+
+/* Verify if multipath is supported by NVMe controller
+ * Returns:
+ *     0 - not supported
+ *     1 - supported
+ */
+int is_multipath_nvme(int disk_fd)
+{
+       char path_buf[PATH_MAX];
+       char ns_path[PATH_MAX];
+       char *kname = fd2kname(disk_fd);
+
+       if (!kname)
+               return 0;
+       sprintf(path_buf, "/sys/block/%s", kname);
+
+       if (!realpath(path_buf, ns_path))
+               return 0;
+
+       if (strncmp(ns_path, NVME_SUBSYS_PATH, strlen(NVME_SUBSYS_PATH)) == 0)
+               return 1;
+
+       return 0;
+}
index 7371478e12fbbfece2c97d277b8587b05a4307c4..8396a0f1428d9a5145a6e14784c3fd667d763820 100644 (file)
@@ -236,6 +236,7 @@ static inline char *guid_str(char *buf, struct efi_guid guid)
        return buf;
 }
 
+char *get_nvme_multipath_dev_hw_path(const char *dev_path);
 char *diskfd_to_devpath(int fd);
 __u16 devpath_to_vendor(const char *dev_path);
 struct sys_dev *find_driver_devices(const char *bus, const char *driver);
@@ -252,4 +253,5 @@ const struct imsm_orom *get_orom_by_device_id(__u16 device_id);
 struct sys_dev *device_by_id(__u16 device_id);
 struct sys_dev *device_by_id_and_path(__u16 device_id, const char *path);
 int imsm_is_nvme_supported(int disk_fd, int verbose);
+int is_multipath_nvme(int disk_fd);
 char *vmd_domain_to_controller(struct sys_dev *hba, char *buf);
index 2bfcad15cc5d0993cbc79c8080e488518a3c7c8d..6617dd6db79b979ef6ea51bbbcdbab95fccd064e 100644 (file)
@@ -2386,9 +2386,9 @@ static int ahci_enumerate_ports(const char *hba_path, int port_count, int host_b
 static int print_nvme_info(struct sys_dev *hba)
 {
        char buf[1024];
+       char *device_path;
        struct dirent *ent;
        DIR *dir;
-       char *rp;
        int fd;
 
        dir = opendir("/sys/block/");
@@ -2397,19 +2397,23 @@ static int print_nvme_info(struct sys_dev *hba)
 
        for (ent = readdir(dir); ent; ent = readdir(dir)) {
                if (strstr(ent->d_name, "nvme")) {
-                       sprintf(buf, "/sys/block/%s", ent->d_name);
-                       rp = realpath(buf, NULL);
-                       if (!rp)
+                       fd = open_dev(ent->d_name);
+                       if (fd < 0)
                                continue;
-                       if (path_attached_to_hba(rp, hba->path)) {
-                               fd = open_dev(ent->d_name);
-                               if (!imsm_is_nvme_supported(fd, 0)) {
-                                       if (fd >= 0)
-                                               close(fd);
-                                       free(rp);
-                                       continue;
-                               }
 
+                       if (!imsm_is_nvme_supported(fd, 0)) {
+                               if (fd >= 0)
+                                       close(fd);
+                               continue;
+                       }
+
+                       device_path = diskfd_to_devpath(fd);
+                       if (!device_path) {
+                               close(fd);
+                               continue;
+                       }
+
+                       if (path_attached_to_hba(device_path, hba->path)) {
                                fd2devname(fd, buf);
                                if (hba->type == SYS_DEV_VMD)
                                        printf(" NVMe under VMD : %s", buf);
@@ -2420,9 +2424,9 @@ static int print_nvme_info(struct sys_dev *hba)
                                        printf(" (%s)\n", buf);
                                else
                                        printf("()\n");
-                               close(fd);
                        }
-                       free(rp);
+                       free(device_path);
+                       close(fd);
                }
        }
 
@@ -5938,6 +5942,7 @@ static int add_to_super_imsm(struct supertype *st, mdu_disk_info_t *dk,
                int i;
                char *devpath = diskfd_to_devpath(fd);
                char controller_path[PATH_MAX];
+               char *controller_name;
 
                if (!devpath) {
                        pr_err("failed to get devpath, aborting\n");
@@ -5948,6 +5953,11 @@ static int add_to_super_imsm(struct supertype *st, mdu_disk_info_t *dk,
                }
 
                snprintf(controller_path, PATH_MAX-1, "%s/device", devpath);
+
+               controller_name = basename(devpath);
+               if (is_multipath_nvme(fd))
+                       pr_err("%s controller supports Multi-Path I/O, Intel (R) VROC does not support multipathing\n", controller_name);
+
                free(devpath);
 
                if (!imsm_is_nvme_supported(dd->fd, 1)) {