|
|
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 |
|