Blame SOURCES/0006-imsm-Limit-support-to-the-lowest-namespace.patch

7140c6
From 8662f92d71f1f88589061272606b8b673d31de05 Mon Sep 17 00:00:00 2001
7140c6
From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
7140c6
Date: Mon, 17 May 2021 16:39:02 +0200
7140c6
Subject: [PATCH 06/15] imsm: Limit support to the lowest namespace
7140c6
7140c6
First namespace existence is not quaranted by NVMe specification.
7140c6
Instead first the smallest one shall be chosen.
7140c6
7140c6
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
7140c6
Signed-off-by: Jes Sorensen <jsorensen@fb.com>
7140c6
---
7140c6
 platform-intel.c |  81 ++++++++++++++++++++++++++----------
7140c6
 platform-intel.h |   2 +-
7140c6
 super-intel.c    | 124 +++++++++++++++++++++++++++----------------------------
7140c6
 3 files changed, 123 insertions(+), 84 deletions(-)
7140c6
7140c6
diff --git a/platform-intel.c b/platform-intel.c
7140c6
index 9401784..5a8729e 100644
7140c6
--- a/platform-intel.c
7140c6
+++ b/platform-intel.c
7140c6
@@ -879,36 +879,75 @@ char *vmd_domain_to_controller(struct sys_dev *hba, char *buf)
7140c6
 	closedir(dir);
7140c6
 	return NULL;
7140c6
 }
7140c6
-/* Verify that NVMe drive is supported by IMSM
7140c6
+
7140c6
+/* Scan over all controller's namespaces and compare nsid value to verify if
7140c6
+ * current one is supported. The routine doesn't check IMSM capabilities for
7140c6
+ * namespace. Only one nvme namespace is supported by IMSM.
7140c6
+ * Paramteres:
7140c6
+ *	fd - open descriptor to the nvme namespace
7140c6
+ *	verbose - error logging level
7140c6
  * Returns:
7140c6
- *	0 - not supported
7140c6
- *	1 - supported
7140c6
+ *	1 - if namespace is supported
7140c6
+ *	0 - otherwise
7140c6
  */
7140c6
-int imsm_is_nvme_supported(int disk_fd, int verbose)
7140c6
+int imsm_is_nvme_namespace_supported(int fd, int verbose)
7140c6
 {
7140c6
-	char nsid_path[PATH_MAX];
7140c6
-	char buf[PATH_MAX];
7140c6
-	struct stat stb;
7140c6
+	DIR *dir = NULL;
7140c6
+	struct dirent *ent;
7140c6
+	char cntrl_path[PATH_MAX];
7140c6
+	char ns_path[PATH_MAX];
7140c6
+	unsigned long long lowest_nsid = ULLONG_MAX;
7140c6
+	unsigned long long this_nsid;
7140c6
+	int rv = 0;
7140c6
 
7140c6
-	if (disk_fd < 0)
7140c6
-		return 0;
7140c6
 
7140c6
-	if (fstat(disk_fd, &stb))
7140c6
-		return 0;
7140c6
+	if (!diskfd_to_devpath(fd, 1, cntrl_path) ||
7140c6
+	    !diskfd_to_devpath(fd, 0, ns_path)) {
7140c6
+		if (verbose)
7140c6
+			pr_err("Cannot get device paths\n");
7140c6
+		goto abort;
7140c6
+	}
7140c6
 
7140c6
-	snprintf(nsid_path, PATH_MAX-1, "/sys/dev/block/%d:%d/nsid",
7140c6
-		 major(stb.st_rdev), minor(stb.st_rdev));
7140c6
 
7140c6
-	if (load_sys(nsid_path, buf, sizeof(buf))) {
7140c6
-		pr_err("Cannot read %s, rejecting drive\n", nsid_path);
7140c6
-		return 0;
7140c6
-	}
7140c6
-	if (strtoll(buf, NULL, 10) != 1) {
7140c6
+	if (devpath_to_ll(ns_path, "nsid", &this_nsid)) {
7140c6
 		if (verbose)
7140c6
-			pr_err("Only first namespace is supported by IMSM, aborting\n");
7140c6
-		return 0;
7140c6
+			pr_err("Cannot read nsid value for %s",
7140c6
+			       basename(ns_path));
7140c6
+		goto abort;
7140c6
 	}
7140c6
-	return 1;
7140c6
+
7140c6
+	dir = opendir(cntrl_path);
7140c6
+	if (!dir)
7140c6
+		goto abort;
7140c6
+
7140c6
+	/* The lowest nvme namespace is supported */
7140c6
+	for (ent = readdir(dir); ent; ent = readdir(dir)) {
7140c6
+		unsigned long long curr_nsid;
7140c6
+		char curr_ns_path[PATH_MAX + 256];
7140c6
+
7140c6
+		if (!strstr(ent->d_name, "nvme"))
7140c6
+			continue;
7140c6
+
7140c6
+		snprintf(curr_ns_path, sizeof(curr_ns_path), "%s/%s",
7140c6
+			 cntrl_path, ent->d_name);
7140c6
+
7140c6
+		if (devpath_to_ll(curr_ns_path, "nsid", &curr_nsid))
7140c6
+			goto abort;
7140c6
+
7140c6
+		if (lowest_nsid > curr_nsid)
7140c6
+			lowest_nsid = curr_nsid;
7140c6
+	}
7140c6
+
7140c6
+	if (this_nsid == lowest_nsid)
7140c6
+		rv = 1;
7140c6
+	else if (verbose)
7140c6
+		pr_err("IMSM is supported on the lowest NVMe namespace\n");
7140c6
+
7140c6
+abort:
7140c6
+	if (dir)
7140c6
+		closedir(dir);
7140c6
+
7140c6
+	return rv;
7140c6
 }
7140c6
 
7140c6
 /* Verify if multipath is supported by NVMe controller
7140c6
diff --git a/platform-intel.h b/platform-intel.h
7140c6
index 45d98cd..6238d23 100644
7140c6
--- a/platform-intel.h
7140c6
+++ b/platform-intel.h
7140c6
@@ -254,6 +254,6 @@ const struct orom_entry *get_orom_entry_by_device_id(__u16 dev_id);
7140c6
 const struct imsm_orom *get_orom_by_device_id(__u16 device_id);
7140c6
 struct sys_dev *device_by_id(__u16 device_id);
7140c6
 struct sys_dev *device_by_id_and_path(__u16 device_id, const char *path);
7140c6
-int imsm_is_nvme_supported(int disk_fd, int verbose);
7140c6
 int is_multipath_nvme(int disk_fd);
7140c6
+int imsm_is_nvme_namespace_supported(int disk_fd, int verbose);
7140c6
 char *vmd_domain_to_controller(struct sys_dev *hba, char *buf);
7140c6
diff --git a/super-intel.c b/super-intel.c
7140c6
index c352f50..fdcefb6 100644
7140c6
--- a/super-intel.c
7140c6
+++ b/super-intel.c
7140c6
@@ -2381,49 +2381,51 @@ static int ahci_enumerate_ports(const char *hba_path, int port_count, int host_b
7140c6
 
7140c6
 static int print_nvme_info(struct sys_dev *hba)
7140c6
 {
7140c6
-	char buf[1024];
7140c6
-	char *device_path;
7140c6
 	struct dirent *ent;
7140c6
 	DIR *dir;
7140c6
-	int fd;
7140c6
 
7140c6
 	dir = opendir("/sys/block/");
7140c6
 	if (!dir)
7140c6
 		return 1;
7140c6
 
7140c6
 	for (ent = readdir(dir); ent; ent = readdir(dir)) {
7140c6
-		if (strstr(ent->d_name, "nvme")) {
7140c6
-			fd = open_dev(ent->d_name);
7140c6
-			if (fd < 0)
7140c6
-				continue;
7140c6
+		char ns_path[PATH_MAX];
7140c6
+		char cntrl_path[PATH_MAX];
7140c6
+		char buf[PATH_MAX];
7140c6
+		int fd = -1;
7140c6
 
7140c6
-			if (!imsm_is_nvme_supported(fd, 0)) {
7140c6
-				if (fd >= 0)
7140c6
-					close(fd);
7140c6
-				continue;
7140c6
-			}
7140c6
+		if (!strstr(ent->d_name, "nvme"))
7140c6
+			goto skip;
7140c6
 
7140c6
-			device_path = diskfd_to_devpath(fd, 1, NULL);
7140c6
-			if (!device_path) {
7140c6
-				close(fd);
7140c6
-				continue;
7140c6
-			}
7140c6
+		fd = open_dev(ent->d_name);
7140c6
+		if (fd < 0)
7140c6
+			goto skip;
7140c6
 
7140c6
-			if (path_attached_to_hba(device_path, hba->path)) {
7140c6
-				fd2devname(fd, buf);
7140c6
-				if (hba->type == SYS_DEV_VMD)
7140c6
-					printf(" NVMe under VMD : %s", buf);
7140c6
-				else if (hba->type == SYS_DEV_NVME)
7140c6
-					printf("    NVMe Device : %s", buf);
7140c6
-				if (!imsm_read_serial(fd, NULL, (__u8 *)buf,
7140c6
-						      sizeof(buf)))
7140c6
-					printf(" (%s)\n", buf);
7140c6
-				else
7140c6
-					printf("()\n");
7140c6
-			}
7140c6
-			free(device_path);
7140c6
+		if (!diskfd_to_devpath(fd, 0, ns_path) ||
7140c6
+		    !diskfd_to_devpath(fd, 1, cntrl_path))
7140c6
+			goto skip;
7140c6
+
7140c6
+		if (!path_attached_to_hba(cntrl_path, hba->path))
7140c6
+			goto skip;
7140c6
+
7140c6
+		if (!imsm_is_nvme_namespace_supported(fd, 0))
7140c6
+			goto skip;
7140c6
+
7140c6
+		fd2devname(fd, buf);
7140c6
+		if (hba->type == SYS_DEV_VMD)
7140c6
+			printf(" NVMe under VMD : %s", buf);
7140c6
+		else if (hba->type == SYS_DEV_NVME)
7140c6
+			printf("    NVMe Device : %s", buf);
7140c6
+
7140c6
+		if (!imsm_read_serial(fd, NULL, (__u8 *)buf,
7140c6
+				      sizeof(buf)))
7140c6
+			printf(" (%s)\n", buf);
7140c6
+		else
7140c6
+			printf("()\n");
7140c6
+
7140c6
+skip:
7140c6
+		if (fd > -1)
7140c6
 			close(fd);
7140c6
-		}
7140c6
 	}
7140c6
 
7140c6
 	closedir(dir);
7140c6
@@ -5933,14 +5935,8 @@ static int add_to_super_imsm(struct supertype *st, mdu_disk_info_t *dk,
7140c6
 
7140c6
 		if (!diskfd_to_devpath(fd, 2, pci_dev_path) ||
7140c6
 		    !diskfd_to_devpath(fd, 1, cntrl_path)) {
7140c6
-			pr_err("failed to get dev_path, aborting\n");
7140c6
-			if (dd->devname)
7140c6
-				free(dd->devname);
7140c6
-			free(dd);
7140c6
-			return 1;
7140c6
-		}
7140c6
+			pr_err("failed to get dev paths, aborting\n");
7140c6
 
7140c6
-		if (!imsm_is_nvme_supported(dd->fd, 1)) {
7140c6
 			if (dd->devname)
7140c6
 				free(dd->devname);
7140c6
 			free(dd);
7140c6
@@ -6665,7 +6661,7 @@ static int validate_geometry_imsm_container(struct supertype *st, int level,
7140c6
 {
7140c6
 	int fd;
7140c6
 	unsigned long long ldsize;
7140c6
-	struct intel_super *super;
7140c6
+	struct intel_super *super = NULL;
7140c6
 	int rv = 0;
7140c6
 
7140c6
 	if (level != LEVEL_CONTAINER)
7140c6
@@ -6680,24 +6676,18 @@ static int validate_geometry_imsm_container(struct supertype *st, int level,
7140c6
 				dev, strerror(errno));
7140c6
 		return 0;
7140c6
 	}
7140c6
-	if (!get_dev_size(fd, dev, &ldsize)) {
7140c6
-		close(fd);
7140c6
-		return 0;
7140c6
-	}
7140c6
+	if (!get_dev_size(fd, dev, &ldsize))
7140c6
+		goto exit;
7140c6
 
7140c6
 	/* capabilities retrieve could be possible
7140c6
 	 * note that there is no fd for the disks in array.
7140c6
 	 */
7140c6
 	super = alloc_super();
7140c6
-	if (!super) {
7140c6
-		close(fd);
7140c6
-		return 0;
7140c6
-	}
7140c6
-	if (!get_dev_sector_size(fd, NULL, &super->sector_size)) {
7140c6
-		close(fd);
7140c6
-		free_imsm(super);
7140c6
-		return 0;
7140c6
-	}
7140c6
+	if (!super)
7140c6
+		goto exit;
7140c6
+
7140c6
+	if (!get_dev_sector_size(fd, NULL, &super->sector_size))
7140c6
+		goto exit;
7140c6
 
7140c6
 	rv = find_intel_hba_capability(fd, super, verbose > 0 ? dev : NULL);
7140c6
 	if (rv != 0) {
7140c6
@@ -6708,32 +6698,42 @@ static int validate_geometry_imsm_container(struct supertype *st, int level,
7140c6
 			fd, str, super->orom, rv, raiddisks);
7140c6
 #endif
7140c6
 		/* no orom/efi or non-intel hba of the disk */
7140c6
-		close(fd);
7140c6
-		free_imsm(super);
7140c6
-		return 0;
7140c6
+		rv = 0;
7140c6
+		goto exit;
7140c6
 	}
7140c6
-	close(fd);
7140c6
 	if (super->orom) {
7140c6
 		if (raiddisks > super->orom->tds) {
7140c6
 			if (verbose)
7140c6
 				pr_err("%d exceeds maximum number of platform supported disks: %d\n",
7140c6
 					raiddisks, super->orom->tds);
7140c6
-			free_imsm(super);
7140c6
-			return 0;
7140c6
+			goto exit;
7140c6
 		}
7140c6
 		if ((super->orom->attr & IMSM_OROM_ATTR_2TB_DISK) == 0 &&
7140c6
 		    (ldsize >> 9) >> 32 > 0) {
7140c6
 			if (verbose)
7140c6
 				pr_err("%s exceeds maximum platform supported size\n", dev);
7140c6
-			free_imsm(super);
7140c6
-			return 0;
7140c6
+			goto exit;
7140c6
+		}
7140c6
+
7140c6
+		if (super->hba->type == SYS_DEV_VMD ||
7140c6
+		    super->hba->type == SYS_DEV_NVME) {
7140c6
+			if (!imsm_is_nvme_namespace_supported(fd, 1)) {
7140c6
+				if (verbose)
7140c6
+					pr_err("NVMe namespace %s is not supported by IMSM\n",
7140c6
+						basename(dev));
7140c6
+				goto exit;
7140c6
+			}
7140c6
 		}
7140c6
 	}
7140c6
 
7140c6
 	*freesize = avail_size_imsm(st, ldsize >> 9, data_offset);
7140c6
-	free_imsm(super);
7140c6
+	rv = 1;
7140c6
+exit:
7140c6
+	if (super)
7140c6
+		free_imsm(super);
7140c6
+	close(fd);
7140c6
 
7140c6
-	return 1;
7140c6
+	return rv;
7140c6
 }
7140c6
 
7140c6
 static unsigned long long find_size(struct extent *e, int *idx, int num_extents)
7140c6
-- 
7140c6
2.7.5
7140c6