You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
147 lines
4.1 KiB
147 lines
4.1 KiB
2 months ago
|
From 6e793aeace463d7687656f7ac6968300ba106228 Mon Sep 17 00:00:00 2001
|
||
|
From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||
|
Date: Thu, 8 Aug 2024 13:07:50 +0200
|
||
|
Subject: [PATCH 162/201] imsm: get bus from VMD driver directory
|
||
|
|
||
|
Enumeration of VMD child devices is started early, kernel is not waiting
|
||
|
for VMD enumeration to finish. It causes that:
|
||
|
/sys/bus/pci/drivers/vmd/{dev}/domain/device link might be not yet ready.
|
||
|
|
||
|
With PCI gen5 devices we can observe that mdadm is failing to start IMSM
|
||
|
raid arrays because of that. In that case, it needs to find bus path
|
||
|
manually.
|
||
|
|
||
|
Look for bus device in VMD driver directory if realpath() failed with
|
||
|
ENOENT.
|
||
|
|
||
|
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||
|
---
|
||
|
platform-intel.c | 88 ++++++++++++++++++++++++++++++++++++++++++------
|
||
|
1 file changed, 77 insertions(+), 11 deletions(-)
|
||
|
|
||
|
diff --git a/platform-intel.c b/platform-intel.c
|
||
|
index 9705c925..d0ef9111 100644
|
||
|
--- a/platform-intel.c
|
||
|
+++ b/platform-intel.c
|
||
|
@@ -105,12 +105,75 @@ static void free_sys_dev(struct sys_dev **list)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
+/**
|
||
|
+ * vmd_find_pci_bus() - look for PCI bus created by VMD.
|
||
|
+ * @vmd_path: path to vmd driver.
|
||
|
+ * @buf: return buffer, must be PATH_MAX.
|
||
|
+ *
|
||
|
+ * Each VMD device represents one domain and each VMD device adds separate PCI bus.
|
||
|
+ * IMSM must know VMD domains, therefore it needs to determine and follow buses.
|
||
|
+ *
|
||
|
+ */
|
||
|
+mdadm_status_t vmd_find_pci_bus(char *vmd_path, char *buf)
|
||
|
+{
|
||
|
+ char tmp[PATH_MAX];
|
||
|
+ struct dirent *ent;
|
||
|
+ DIR *vmd_dir;
|
||
|
+ char *rp_ret;
|
||
|
+
|
||
|
+ snprintf(tmp, PATH_MAX, "%s/domain/device", vmd_path);
|
||
|
+
|
||
|
+ rp_ret = realpath(tmp, buf);
|
||
|
+
|
||
|
+ if (rp_ret)
|
||
|
+ return MDADM_STATUS_SUCCESS;
|
||
|
+
|
||
|
+ if (errno != ENOENT)
|
||
|
+ return MDADM_STATUS_ERROR;
|
||
|
+
|
||
|
+ /*
|
||
|
+ * If it is done early, there is a chance that kernel is still enumerating VMD device but
|
||
|
+ * kernel did enough to start enumerating child devices, {vmd_path}/domain/device link may
|
||
|
+ * not exist yet. We have to look into @vmd_path directory and find it ourselves.
|
||
|
+ */
|
||
|
+
|
||
|
+ vmd_dir = opendir(vmd_path);
|
||
|
+
|
||
|
+ if (!vmd_dir)
|
||
|
+ return MDADM_STATUS_ERROR;
|
||
|
+
|
||
|
+ for (ent = readdir(vmd_dir); ent; ent = readdir(vmd_dir)) {
|
||
|
+ static const char pci[] = "pci";
|
||
|
+
|
||
|
+ /**
|
||
|
+ * Pci bus must have form pciXXXXX:XX, where X is a digit i.e pci10000:00.
|
||
|
+ * We do not check digits here, it is sysfs so it should be safe to check
|
||
|
+ * length and ':' position only.
|
||
|
+ */
|
||
|
+ if (strncmp(ent->d_name, pci, strlen(pci)) != 0)
|
||
|
+ continue;
|
||
|
+
|
||
|
+ if (ent->d_name[8] != ':' || ent->d_name[11] != 0)
|
||
|
+ continue;
|
||
|
+ break;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (!ent) {
|
||
|
+ closedir(vmd_dir);
|
||
|
+ return MDADM_STATUS_ERROR;
|
||
|
+ }
|
||
|
+
|
||
|
+ snprintf(buf, PATH_MAX, "%s/%s", vmd_path, ent->d_name);
|
||
|
+ closedir(vmd_dir);
|
||
|
+ return MDADM_STATUS_SUCCESS;
|
||
|
+}
|
||
|
+
|
||
|
struct sys_dev *find_driver_devices(const char *bus, const char *driver)
|
||
|
{
|
||
|
/* search sysfs for devices driven by 'driver' */
|
||
|
char path[PATH_MAX];
|
||
|
char link[PATH_MAX];
|
||
|
- char *c, *p;
|
||
|
+ char *c;
|
||
|
DIR *driver_dir;
|
||
|
struct dirent *de;
|
||
|
struct sys_dev *head = NULL;
|
||
|
@@ -142,8 +205,9 @@ struct sys_dev *find_driver_devices(const char *bus, const char *driver)
|
||
|
return NULL;
|
||
|
}
|
||
|
for (de = readdir(driver_dir); de; de = readdir(driver_dir)) {
|
||
|
- int n;
|
||
|
int skip = 0;
|
||
|
+ char *p;
|
||
|
+ int n;
|
||
|
|
||
|
/* is 'de' a device? check that the 'subsystem' link exists and
|
||
|
* that its target matches 'bus'
|
||
|
@@ -195,18 +259,20 @@ struct sys_dev *find_driver_devices(const char *bus, const char *driver)
|
||
|
if (devpath_to_ll(path, "class", &class) != 0)
|
||
|
continue;
|
||
|
|
||
|
- /*
|
||
|
- * Each VMD device (domain) adds separate PCI bus, it is better
|
||
|
- * to store path as a path to that bus (easier further
|
||
|
- * determination which NVMe dev is connected to this particular
|
||
|
- * VMD domain).
|
||
|
- */
|
||
|
if (type == SYS_DEV_VMD) {
|
||
|
- sprintf(path, "/sys/bus/%s/drivers/%s/%s/domain/device",
|
||
|
- bus, driver, de->d_name);
|
||
|
+ char vmd_path[PATH_MAX];
|
||
|
+
|
||
|
+ sprintf(vmd_path, "/sys/bus/%s/drivers/%s/%s", bus, driver, de->d_name);
|
||
|
+
|
||
|
+ if (vmd_find_pci_bus(vmd_path, path)) {
|
||
|
+ pr_err("Cannot determine VMD bus for %s\n", vmd_path);
|
||
|
+ continue;
|
||
|
+ }
|
||
|
}
|
||
|
+
|
||
|
p = realpath(path, NULL);
|
||
|
- if (p == NULL) {
|
||
|
+
|
||
|
+ if (!p) {
|
||
|
pr_err("Unable to get real path for '%s'\n", path);
|
||
|
continue;
|
||
|
}
|
||
|
--
|
||
|
2.41.0
|
||
|
|