]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
imsm: Limit support to the lowest namespace
authorMariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Mon, 17 May 2021 14:39:02 +0000 (16:39 +0200)
committerJes Sorensen <jsorensen@fb.com>
Wed, 26 May 2021 11:26:32 +0000 (07:26 -0400)
First namespace existence is not quaranted by NVMe specification.
Instead first the smallest one shall be chosen.

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 94017841fa5398f14c5c256d0ba5926796d99c16..5a8729e7c4ae43be03fcc9d269a8792bd22d3cdf 100644 (file)
@@ -879,36 +879,75 @@ char *vmd_domain_to_controller(struct sys_dev *hba, char *buf)
        closedir(dir);
        return NULL;
 }
-/* Verify that NVMe drive is supported by IMSM
+
+/* Scan over all controller's namespaces and compare nsid value to verify if
+ * current one is supported. The routine doesn't check IMSM capabilities for
+ * namespace. Only one nvme namespace is supported by IMSM.
+ * Paramteres:
+ *     fd - open descriptor to the nvme namespace
+ *     verbose - error logging level
  * Returns:
- *     0 - not supported
- *     1 - supported
+ *     1 - if namespace is supported
+ *     0 - otherwise
  */
-int imsm_is_nvme_supported(int disk_fd, int verbose)
+int imsm_is_nvme_namespace_supported(int fd, int verbose)
 {
-       char nsid_path[PATH_MAX];
-       char buf[PATH_MAX];
-       struct stat stb;
+       DIR *dir = NULL;
+       struct dirent *ent;
+       char cntrl_path[PATH_MAX];
+       char ns_path[PATH_MAX];
+       unsigned long long lowest_nsid = ULLONG_MAX;
+       unsigned long long this_nsid;
+       int rv = 0;
 
-       if (disk_fd < 0)
-               return 0;
 
-       if (fstat(disk_fd, &stb))
-               return 0;
+       if (!diskfd_to_devpath(fd, 1, cntrl_path) ||
+           !diskfd_to_devpath(fd, 0, ns_path)) {
+               if (verbose)
+                       pr_err("Cannot get device paths\n");
+               goto abort;
+       }
 
-       snprintf(nsid_path, PATH_MAX-1, "/sys/dev/block/%d:%d/nsid",
-                major(stb.st_rdev), minor(stb.st_rdev));
 
-       if (load_sys(nsid_path, buf, sizeof(buf))) {
-               pr_err("Cannot read %s, rejecting drive\n", nsid_path);
-               return 0;
-       }
-       if (strtoll(buf, NULL, 10) != 1) {
+       if (devpath_to_ll(ns_path, "nsid", &this_nsid)) {
                if (verbose)
-                       pr_err("Only first namespace is supported by IMSM, aborting\n");
-               return 0;
+                       pr_err("Cannot read nsid value for %s",
+                              basename(ns_path));
+               goto abort;
        }
-       return 1;
+
+       dir = opendir(cntrl_path);
+       if (!dir)
+               goto abort;
+
+       /* The lowest nvme namespace is supported */
+       for (ent = readdir(dir); ent; ent = readdir(dir)) {
+               unsigned long long curr_nsid;
+               char curr_ns_path[PATH_MAX + 256];
+
+               if (!strstr(ent->d_name, "nvme"))
+                       continue;
+
+               snprintf(curr_ns_path, sizeof(curr_ns_path), "%s/%s",
+                        cntrl_path, ent->d_name);
+
+               if (devpath_to_ll(curr_ns_path, "nsid", &curr_nsid))
+                       goto abort;
+
+               if (lowest_nsid > curr_nsid)
+                       lowest_nsid = curr_nsid;
+       }
+
+       if (this_nsid == lowest_nsid)
+               rv = 1;
+       else if (verbose)
+               pr_err("IMSM is supported on the lowest NVMe namespace\n");
+
+abort:
+       if (dir)
+               closedir(dir);
+
+       return rv;
 }
 
 /* Verify if multipath is supported by NVMe controller
index 45d98cddf56a46355e4a0d1ddeb902ebd7cc1023..6238d23f44564c9bfb76968f2eebd267083b305e 100644 (file)
@@ -254,6 +254,6 @@ const struct orom_entry *get_orom_entry_by_device_id(__u16 dev_id);
 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);
+int imsm_is_nvme_namespace_supported(int disk_fd, int verbose);
 char *vmd_domain_to_controller(struct sys_dev *hba, char *buf);
index c352f50cf7c6bd02e0e9b91eb19d45d8078e87a8..fdcefb6156196660a043e65abdfaa378d731ea83 100644 (file)
@@ -2381,49 +2381,51 @@ 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;
-       int fd;
 
        dir = opendir("/sys/block/");
        if (!dir)
                return 1;
 
        for (ent = readdir(dir); ent; ent = readdir(dir)) {
-               if (strstr(ent->d_name, "nvme")) {
-                       fd = open_dev(ent->d_name);
-                       if (fd < 0)
-                               continue;
+               char ns_path[PATH_MAX];
+               char cntrl_path[PATH_MAX];
+               char buf[PATH_MAX];
+               int fd = -1;
 
-                       if (!imsm_is_nvme_supported(fd, 0)) {
-                               if (fd >= 0)
-                                       close(fd);
-                               continue;
-                       }
+               if (!strstr(ent->d_name, "nvme"))
+                       goto skip;
 
-                       device_path = diskfd_to_devpath(fd, 1, NULL);
-                       if (!device_path) {
-                               close(fd);
-                               continue;
-                       }
+               fd = open_dev(ent->d_name);
+               if (fd < 0)
+                       goto skip;
 
-                       if (path_attached_to_hba(device_path, hba->path)) {
-                               fd2devname(fd, buf);
-                               if (hba->type == SYS_DEV_VMD)
-                                       printf(" NVMe under VMD : %s", buf);
-                               else if (hba->type == SYS_DEV_NVME)
-                                       printf("    NVMe Device : %s", buf);
-                               if (!imsm_read_serial(fd, NULL, (__u8 *)buf,
-                                                     sizeof(buf)))
-                                       printf(" (%s)\n", buf);
-                               else
-                                       printf("()\n");
-                       }
-                       free(device_path);
+               if (!diskfd_to_devpath(fd, 0, ns_path) ||
+                   !diskfd_to_devpath(fd, 1, cntrl_path))
+                       goto skip;
+
+               if (!path_attached_to_hba(cntrl_path, hba->path))
+                       goto skip;
+
+               if (!imsm_is_nvme_namespace_supported(fd, 0))
+                       goto skip;
+
+               fd2devname(fd, buf);
+               if (hba->type == SYS_DEV_VMD)
+                       printf(" NVMe under VMD : %s", buf);
+               else if (hba->type == SYS_DEV_NVME)
+                       printf("    NVMe Device : %s", buf);
+
+               if (!imsm_read_serial(fd, NULL, (__u8 *)buf,
+                                     sizeof(buf)))
+                       printf(" (%s)\n", buf);
+               else
+                       printf("()\n");
+
+skip:
+               if (fd > -1)
                        close(fd);
-               }
        }
 
        closedir(dir);
@@ -5933,14 +5935,8 @@ static int add_to_super_imsm(struct supertype *st, mdu_disk_info_t *dk,
 
                if (!diskfd_to_devpath(fd, 2, pci_dev_path) ||
                    !diskfd_to_devpath(fd, 1, cntrl_path)) {
-                       pr_err("failed to get dev_path, aborting\n");
-                       if (dd->devname)
-                               free(dd->devname);
-                       free(dd);
-                       return 1;
-               }
+                       pr_err("failed to get dev paths, aborting\n");
 
-               if (!imsm_is_nvme_supported(dd->fd, 1)) {
                        if (dd->devname)
                                free(dd->devname);
                        free(dd);
@@ -6665,7 +6661,7 @@ static int validate_geometry_imsm_container(struct supertype *st, int level,
 {
        int fd;
        unsigned long long ldsize;
-       struct intel_super *super;
+       struct intel_super *super = NULL;
        int rv = 0;
 
        if (level != LEVEL_CONTAINER)
@@ -6680,24 +6676,18 @@ static int validate_geometry_imsm_container(struct supertype *st, int level,
                                dev, strerror(errno));
                return 0;
        }
-       if (!get_dev_size(fd, dev, &ldsize)) {
-               close(fd);
-               return 0;
-       }
+       if (!get_dev_size(fd, dev, &ldsize))
+               goto exit;
 
        /* capabilities retrieve could be possible
         * note that there is no fd for the disks in array.
         */
        super = alloc_super();
-       if (!super) {
-               close(fd);
-               return 0;
-       }
-       if (!get_dev_sector_size(fd, NULL, &super->sector_size)) {
-               close(fd);
-               free_imsm(super);
-               return 0;
-       }
+       if (!super)
+               goto exit;
+
+       if (!get_dev_sector_size(fd, NULL, &super->sector_size))
+               goto exit;
 
        rv = find_intel_hba_capability(fd, super, verbose > 0 ? dev : NULL);
        if (rv != 0) {
@@ -6708,32 +6698,42 @@ static int validate_geometry_imsm_container(struct supertype *st, int level,
                        fd, str, super->orom, rv, raiddisks);
 #endif
                /* no orom/efi or non-intel hba of the disk */
-               close(fd);
-               free_imsm(super);
-               return 0;
+               rv = 0;
+               goto exit;
        }
-       close(fd);
        if (super->orom) {
                if (raiddisks > super->orom->tds) {
                        if (verbose)
                                pr_err("%d exceeds maximum number of platform supported disks: %d\n",
                                        raiddisks, super->orom->tds);
-                       free_imsm(super);
-                       return 0;
+                       goto exit;
                }
                if ((super->orom->attr & IMSM_OROM_ATTR_2TB_DISK) == 0 &&
                    (ldsize >> 9) >> 32 > 0) {
                        if (verbose)
                                pr_err("%s exceeds maximum platform supported size\n", dev);
-                       free_imsm(super);
-                       return 0;
+                       goto exit;
+               }
+
+               if (super->hba->type == SYS_DEV_VMD ||
+                   super->hba->type == SYS_DEV_NVME) {
+                       if (!imsm_is_nvme_namespace_supported(fd, 1)) {
+                               if (verbose)
+                                       pr_err("NVMe namespace %s is not supported by IMSM\n",
+                                               basename(dev));
+                               goto exit;
+                       }
                }
        }
 
        *freesize = avail_size_imsm(st, ldsize >> 9, data_offset);
-       free_imsm(super);
+       rv = 1;
+exit:
+       if (super)
+               free_imsm(super);
+       close(fd);
 
-       return 1;
+       return rv;
 }
 
 static unsigned long long find_size(struct extent *e, int *idx, int num_extents)