|
|
7140c6 |
From 7c798f870900f6f4d4647dd3c88318524d7ccee4 Mon Sep 17 00:00:00 2001
|
|
|
7140c6 |
From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
|
|
7140c6 |
Date: Mon, 17 May 2021 16:39:00 +0200
|
|
|
7140c6 |
Subject: [PATCH 04/15] imsm: add generic method to resolve "device" links
|
|
|
7140c6 |
|
|
|
7140c6 |
Each virtual device is linked with parent by "device". This patch adds
|
|
|
7140c6 |
possibility to get previous device in sysfs tree.
|
|
|
7140c6 |
|
|
|
7140c6 |
Depending on device type, there is a different amount of virutal
|
|
|
7140c6 |
layers. The best we can do is allow to directly specify how many
|
|
|
7140c6 |
"device" links need to be resolved. This approach also allows to get
|
|
|
7140c6 |
previous virtual device, which may contain some attributes.
|
|
|
7140c6 |
|
|
|
7140c6 |
Simplify fd2devname, this function doesn't require new functionality and
|
|
|
7140c6 |
shall use generic fd2kname.
|
|
|
7140c6 |
|
|
|
7140c6 |
For nvme drives represented via nvme-subystem when path to block
|
|
|
7140c6 |
device if requested, then return it without translation.
|
|
|
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 | 75 ++++++++++++++++++++++++++++++++++++++------------------
|
|
|
7140c6 |
platform-intel.h | 4 +--
|
|
|
7140c6 |
super-intel.c | 63 ++++++++++++++++++-----------------------------
|
|
|
7140c6 |
3 files changed, 77 insertions(+), 65 deletions(-)
|
|
|
7140c6 |
|
|
|
7140c6 |
diff --git a/platform-intel.c b/platform-intel.c
|
|
|
7140c6 |
index 2da152f..2ed63ed 100644
|
|
|
7140c6 |
--- a/platform-intel.c
|
|
|
7140c6 |
+++ b/platform-intel.c
|
|
|
7140c6 |
@@ -712,28 +712,61 @@ char *get_nvme_multipath_dev_hw_path(const char *dev_path)
|
|
|
7140c6 |
return rp;
|
|
|
7140c6 |
}
|
|
|
7140c6 |
|
|
|
7140c6 |
-char *devt_to_devpath(dev_t dev)
|
|
|
7140c6 |
+/* Description: Return part or whole realpath for the dev
|
|
|
7140c6 |
+ * Parameters:
|
|
|
7140c6 |
+ * dev - the device to be quered
|
|
|
7140c6 |
+ * dev_level - level of "/device" entries. It allows to caller to access
|
|
|
7140c6 |
+ * virtual or physical devices which are on "path" to quered
|
|
|
7140c6 |
+ * one.
|
|
|
7140c6 |
+ * buf - optional, must be PATH_MAX size. If set, then will be used.
|
|
|
7140c6 |
+ */
|
|
|
7140c6 |
+char *devt_to_devpath(dev_t dev, int dev_level, char *buf)
|
|
|
7140c6 |
{
|
|
|
7140c6 |
- char device[46];
|
|
|
7140c6 |
- char *rp;
|
|
|
7140c6 |
- char *buf;
|
|
|
7140c6 |
+ char device[PATH_MAX];
|
|
|
7140c6 |
+ char *hw_path;
|
|
|
7140c6 |
+ int i;
|
|
|
7140c6 |
+ unsigned long device_free_len = sizeof(device) - 1;
|
|
|
7140c6 |
+ char dev_str[] = "/device";
|
|
|
7140c6 |
+ unsigned long dev_str_len = strlen(dev_str);
|
|
|
7140c6 |
+
|
|
|
7140c6 |
+ snprintf(device, sizeof(device), "/sys/dev/block/%d:%d", major(dev),
|
|
|
7140c6 |
+ minor(dev));
|
|
|
7140c6 |
+
|
|
|
7140c6 |
+ /* If caller wants block device, return path to it even if it is exposed
|
|
|
7140c6 |
+ * via virtual layer.
|
|
|
7140c6 |
+ */
|
|
|
7140c6 |
+ if (dev_level == 0)
|
|
|
7140c6 |
+ return realpath(device, buf);
|
|
|
7140c6 |
|
|
|
7140c6 |
- sprintf(device, "/sys/dev/block/%d:%d/device", major(dev), minor(dev));
|
|
|
7140c6 |
+ device_free_len -= strlen(device);
|
|
|
7140c6 |
+ for (i = 0; i < dev_level; i++) {
|
|
|
7140c6 |
+ if (device_free_len < dev_str_len)
|
|
|
7140c6 |
+ return NULL;
|
|
|
7140c6 |
|
|
|
7140c6 |
- rp = realpath(device, NULL);
|
|
|
7140c6 |
- if (!rp)
|
|
|
7140c6 |
- return NULL;
|
|
|
7140c6 |
+ strncat(device, dev_str, device_free_len);
|
|
|
7140c6 |
|
|
|
7140c6 |
- buf = get_nvme_multipath_dev_hw_path(rp);
|
|
|
7140c6 |
- if (buf) {
|
|
|
7140c6 |
- free(rp);
|
|
|
7140c6 |
- return buf;
|
|
|
7140c6 |
+ /* Resolve nvme-subsystem abstraction if needed
|
|
|
7140c6 |
+ */
|
|
|
7140c6 |
+ device_free_len -= dev_str_len;
|
|
|
7140c6 |
+ if (i == 0) {
|
|
|
7140c6 |
+ char rp[PATH_MAX];
|
|
|
7140c6 |
+
|
|
|
7140c6 |
+ if (!realpath(device, rp))
|
|
|
7140c6 |
+ return NULL;
|
|
|
7140c6 |
+ hw_path = get_nvme_multipath_dev_hw_path(rp);
|
|
|
7140c6 |
+ if (hw_path) {
|
|
|
7140c6 |
+ strcpy(device, hw_path);
|
|
|
7140c6 |
+ device_free_len = sizeof(device) -
|
|
|
7140c6 |
+ strlen(device) - 1;
|
|
|
7140c6 |
+ free(hw_path);
|
|
|
7140c6 |
+ }
|
|
|
7140c6 |
+ }
|
|
|
7140c6 |
}
|
|
|
7140c6 |
|
|
|
7140c6 |
- return rp;
|
|
|
7140c6 |
+ return realpath(device, buf);
|
|
|
7140c6 |
}
|
|
|
7140c6 |
|
|
|
7140c6 |
-char *diskfd_to_devpath(int fd)
|
|
|
7140c6 |
+char *diskfd_to_devpath(int fd, int dev_level, char *buf)
|
|
|
7140c6 |
{
|
|
|
7140c6 |
/* return the device path for a disk, return NULL on error or fd
|
|
|
7140c6 |
* refers to a partition
|
|
|
7140c6 |
@@ -745,7 +778,7 @@ char *diskfd_to_devpath(int fd)
|
|
|
7140c6 |
if (!S_ISBLK(st.st_mode))
|
|
|
7140c6 |
return NULL;
|
|
|
7140c6 |
|
|
|
7140c6 |
- return devt_to_devpath(st.st_rdev);
|
|
|
7140c6 |
+ return devt_to_devpath(st.st_rdev, dev_level, buf);
|
|
|
7140c6 |
}
|
|
|
7140c6 |
|
|
|
7140c6 |
int path_attached_to_hba(const char *disk_path, const char *hba_path)
|
|
|
7140c6 |
@@ -770,7 +803,7 @@ int path_attached_to_hba(const char *disk_path, const char *hba_path)
|
|
|
7140c6 |
|
|
|
7140c6 |
int devt_attached_to_hba(dev_t dev, const char *hba_path)
|
|
|
7140c6 |
{
|
|
|
7140c6 |
- char *disk_path = devt_to_devpath(dev);
|
|
|
7140c6 |
+ char *disk_path = devt_to_devpath(dev, 1, NULL);
|
|
|
7140c6 |
int rc = path_attached_to_hba(disk_path, hba_path);
|
|
|
7140c6 |
|
|
|
7140c6 |
if (disk_path)
|
|
|
7140c6 |
@@ -781,7 +814,7 @@ int devt_attached_to_hba(dev_t dev, const char *hba_path)
|
|
|
7140c6 |
|
|
|
7140c6 |
int disk_attached_to_hba(int fd, const char *hba_path)
|
|
|
7140c6 |
{
|
|
|
7140c6 |
- char *disk_path = diskfd_to_devpath(fd);
|
|
|
7140c6 |
+ char *disk_path = diskfd_to_devpath(fd, 1, NULL);
|
|
|
7140c6 |
int rc = path_attached_to_hba(disk_path, hba_path);
|
|
|
7140c6 |
|
|
|
7140c6 |
if (disk_path)
|
|
|
7140c6 |
@@ -862,15 +895,9 @@ int imsm_is_nvme_supported(int disk_fd, int verbose)
|
|
|
7140c6 |
*/
|
|
|
7140c6 |
int is_multipath_nvme(int disk_fd)
|
|
|
7140c6 |
{
|
|
|
7140c6 |
- char path_buf[PATH_MAX];
|
|
|
7140c6 |
char ns_path[PATH_MAX];
|
|
|
7140c6 |
- char *kname = fd2kname(disk_fd);
|
|
|
7140c6 |
-
|
|
|
7140c6 |
- if (!kname)
|
|
|
7140c6 |
- return 0;
|
|
|
7140c6 |
- sprintf(path_buf, "/sys/block/%s", kname);
|
|
|
7140c6 |
|
|
|
7140c6 |
- if (!realpath(path_buf, ns_path))
|
|
|
7140c6 |
+ if (!diskfd_to_devpath(disk_fd, 0, ns_path))
|
|
|
7140c6 |
return 0;
|
|
|
7140c6 |
|
|
|
7140c6 |
if (strncmp(ns_path, NVME_SUBSYS_PATH, strlen(NVME_SUBSYS_PATH)) == 0)
|
|
|
7140c6 |
diff --git a/platform-intel.h b/platform-intel.h
|
|
|
7140c6 |
index 8396a0f..f93add5 100644
|
|
|
7140c6 |
--- a/platform-intel.h
|
|
|
7140c6 |
+++ b/platform-intel.h
|
|
|
7140c6 |
@@ -237,7 +237,7 @@ static inline char *guid_str(char *buf, struct efi_guid guid)
|
|
|
7140c6 |
}
|
|
|
7140c6 |
|
|
|
7140c6 |
char *get_nvme_multipath_dev_hw_path(const char *dev_path);
|
|
|
7140c6 |
-char *diskfd_to_devpath(int fd);
|
|
|
7140c6 |
+char *diskfd_to_devpath(int fd, int dev_level, char *buf);
|
|
|
7140c6 |
__u16 devpath_to_vendor(const char *dev_path);
|
|
|
7140c6 |
struct sys_dev *find_driver_devices(const char *bus, const char *driver);
|
|
|
7140c6 |
struct sys_dev *find_intel_devices(void);
|
|
|
7140c6 |
@@ -245,7 +245,7 @@ const struct imsm_orom *find_imsm_capability(struct sys_dev *hba);
|
|
|
7140c6 |
const struct imsm_orom *find_imsm_orom(void);
|
|
|
7140c6 |
int disk_attached_to_hba(int fd, const char *hba_path);
|
|
|
7140c6 |
int devt_attached_to_hba(dev_t dev, const char *hba_path);
|
|
|
7140c6 |
-char *devt_to_devpath(dev_t dev);
|
|
|
7140c6 |
+char *devt_to_devpath(dev_t dev, int dev_level, char *buf);
|
|
|
7140c6 |
int path_attached_to_hba(const char *disk_path, const char *hba_path);
|
|
|
7140c6 |
const char *get_sys_dev_type(enum sys_dev_type);
|
|
|
7140c6 |
const struct orom_entry *get_orom_entry_by_device_id(__u16 dev_id);
|
|
|
7140c6 |
diff --git a/super-intel.c b/super-intel.c
|
|
|
7140c6 |
index 5469912..cff8550 100644
|
|
|
7140c6 |
--- a/super-intel.c
|
|
|
7140c6 |
+++ b/super-intel.c
|
|
|
7140c6 |
@@ -694,7 +694,7 @@ static struct sys_dev* find_disk_attached_hba(int fd, const char *devname)
|
|
|
7140c6 |
if (fd < 0)
|
|
|
7140c6 |
disk_path = (char *) devname;
|
|
|
7140c6 |
else
|
|
|
7140c6 |
- disk_path = diskfd_to_devpath(fd);
|
|
|
7140c6 |
+ disk_path = diskfd_to_devpath(fd, 1, NULL);
|
|
|
7140c6 |
|
|
|
7140c6 |
if (!disk_path)
|
|
|
7140c6 |
return 0;
|
|
|
7140c6 |
@@ -2253,7 +2253,7 @@ static int ahci_enumerate_ports(const char *hba_path, int port_count, int host_b
|
|
|
7140c6 |
|
|
|
7140c6 |
if (sscanf(ent->d_name, "%d:%d", &major, &minor) != 2)
|
|
|
7140c6 |
continue;
|
|
|
7140c6 |
- path = devt_to_devpath(makedev(major, minor));
|
|
|
7140c6 |
+ path = devt_to_devpath(makedev(major, minor), 1, NULL);
|
|
|
7140c6 |
if (!path)
|
|
|
7140c6 |
continue;
|
|
|
7140c6 |
if (!path_attached_to_hba(path, hba_path)) {
|
|
|
7140c6 |
@@ -2407,7 +2407,7 @@ static int print_nvme_info(struct sys_dev *hba)
|
|
|
7140c6 |
continue;
|
|
|
7140c6 |
}
|
|
|
7140c6 |
|
|
|
7140c6 |
- device_path = diskfd_to_devpath(fd);
|
|
|
7140c6 |
+ device_path = diskfd_to_devpath(fd, 1, NULL);
|
|
|
7140c6 |
if (!device_path) {
|
|
|
7140c6 |
close(fd);
|
|
|
7140c6 |
continue;
|
|
|
7140c6 |
@@ -4015,28 +4015,13 @@ static int compare_super_imsm(struct supertype *st, struct supertype *tst,
|
|
|
7140c6 |
|
|
|
7140c6 |
static void fd2devname(int fd, char *name)
|
|
|
7140c6 |
{
|
|
|
7140c6 |
- struct stat st;
|
|
|
7140c6 |
- char path[256];
|
|
|
7140c6 |
- char dname[PATH_MAX];
|
|
|
7140c6 |
char *nm;
|
|
|
7140c6 |
- int rv;
|
|
|
7140c6 |
-
|
|
|
7140c6 |
- name[0] = '\0';
|
|
|
7140c6 |
- if (fstat(fd, &st) != 0)
|
|
|
7140c6 |
- return;
|
|
|
7140c6 |
- sprintf(path, "/sys/dev/block/%d:%d",
|
|
|
7140c6 |
- major(st.st_rdev), minor(st.st_rdev));
|
|
|
7140c6 |
|
|
|
7140c6 |
- rv = readlink(path, dname, sizeof(dname)-1);
|
|
|
7140c6 |
- if (rv <= 0)
|
|
|
7140c6 |
+ nm = fd2kname(fd);
|
|
|
7140c6 |
+ if (!nm)
|
|
|
7140c6 |
return;
|
|
|
7140c6 |
|
|
|
7140c6 |
- dname[rv] = '\0';
|
|
|
7140c6 |
- nm = strrchr(dname, '/');
|
|
|
7140c6 |
- if (nm) {
|
|
|
7140c6 |
- nm++;
|
|
|
7140c6 |
- snprintf(name, MAX_RAID_SERIAL_LEN, "/dev/%s", nm);
|
|
|
7140c6 |
- }
|
|
|
7140c6 |
+ snprintf(name, MAX_RAID_SERIAL_LEN, "/dev/%s", nm);
|
|
|
7140c6 |
}
|
|
|
7140c6 |
|
|
|
7140c6 |
static int nvme_get_serial(int fd, void *buf, size_t buf_len)
|
|
|
7140c6 |
@@ -5941,29 +5926,23 @@ static int add_to_super_imsm(struct supertype *st, mdu_disk_info_t *dk,
|
|
|
7140c6 |
free(dd);
|
|
|
7140c6 |
abort();
|
|
|
7140c6 |
}
|
|
|
7140c6 |
+
|
|
|
7140c6 |
if (super->hba && ((super->hba->type == SYS_DEV_NVME) ||
|
|
|
7140c6 |
(super->hba->type == SYS_DEV_VMD))) {
|
|
|
7140c6 |
int i;
|
|
|
7140c6 |
- char *devpath = diskfd_to_devpath(fd);
|
|
|
7140c6 |
- char controller_path[PATH_MAX];
|
|
|
7140c6 |
- char *controller_name;
|
|
|
7140c6 |
+ char cntrl_path[PATH_MAX];
|
|
|
7140c6 |
+ char *cntrl_name;
|
|
|
7140c6 |
+ char pci_dev_path[PATH_MAX];
|
|
|
7140c6 |
|
|
|
7140c6 |
- if (!devpath) {
|
|
|
7140c6 |
- pr_err("failed to get devpath, aborting\n");
|
|
|
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 |
|
|
|
7140c6 |
- snprintf(controller_path, PATH_MAX-1, "%s/device", devpath);
|
|
|
7140c6 |
-
|
|
|
7140c6 |
- controller_name = basename(devpath);
|
|
|
7140c6 |
- if (is_multipath_nvme(fd))
|
|
|
7140c6 |
- pr_err("%s controller supports Multi-Path I/O, Intel (R) VROC does not support multipathing\n", controller_name);
|
|
|
7140c6 |
-
|
|
|
7140c6 |
- free(devpath);
|
|
|
7140c6 |
-
|
|
|
7140c6 |
if (!imsm_is_nvme_supported(dd->fd, 1)) {
|
|
|
7140c6 |
if (dd->devname)
|
|
|
7140c6 |
free(dd->devname);
|
|
|
7140c6 |
@@ -5971,7 +5950,12 @@ static int add_to_super_imsm(struct supertype *st, mdu_disk_info_t *dk,
|
|
|
7140c6 |
return 1;
|
|
|
7140c6 |
}
|
|
|
7140c6 |
|
|
|
7140c6 |
- if (devpath_to_vendor(controller_path) == 0x8086) {
|
|
|
7140c6 |
+ cntrl_name = basename(cntrl_path);
|
|
|
7140c6 |
+ if (is_multipath_nvme(fd))
|
|
|
7140c6 |
+ pr_err("%s controller supports Multi-Path I/O, Intel (R) VROC does not support multipathing\n",
|
|
|
7140c6 |
+ cntrl_name);
|
|
|
7140c6 |
+
|
|
|
7140c6 |
+ if (devpath_to_vendor(pci_dev_path) == 0x8086) {
|
|
|
7140c6 |
/*
|
|
|
7140c6 |
* If Intel's NVMe drive has serial ended with
|
|
|
7140c6 |
* "-A","-B","-1" or "-2" it means that this is "x8"
|
|
|
7140c6 |
@@ -6985,7 +6969,7 @@ get_devices(const char *hba_path)
|
|
|
7140c6 |
char *path = NULL;
|
|
|
7140c6 |
if (sscanf(ent->d_name, "%d:%d", &major, &minor) != 2)
|
|
|
7140c6 |
continue;
|
|
|
7140c6 |
- path = devt_to_devpath(makedev(major, minor));
|
|
|
7140c6 |
+ path = devt_to_devpath(makedev(major, minor), 1, NULL);
|
|
|
7140c6 |
if (!path)
|
|
|
7140c6 |
continue;
|
|
|
7140c6 |
if (!path_attached_to_hba(path, hba_path)) {
|
|
|
7140c6 |
@@ -10648,7 +10632,7 @@ int validate_container_imsm(struct mdinfo *info)
|
|
|
7140c6 |
struct sys_dev *hba = NULL;
|
|
|
7140c6 |
struct sys_dev *intel_devices = find_intel_devices();
|
|
|
7140c6 |
char *dev_path = devt_to_devpath(makedev(info->disk.major,
|
|
|
7140c6 |
- info->disk.minor));
|
|
|
7140c6 |
+ info->disk.minor), 1, NULL);
|
|
|
7140c6 |
|
|
|
7140c6 |
for (idev = intel_devices; idev; idev = idev->next) {
|
|
|
7140c6 |
if (dev_path && strstr(dev_path, idev->path)) {
|
|
|
7140c6 |
@@ -10669,7 +10653,8 @@ int validate_container_imsm(struct mdinfo *info)
|
|
|
7140c6 |
struct mdinfo *dev;
|
|
|
7140c6 |
|
|
|
7140c6 |
for (dev = info->next; dev; dev = dev->next) {
|
|
|
7140c6 |
- dev_path = devt_to_devpath(makedev(dev->disk.major, dev->disk.minor));
|
|
|
7140c6 |
+ dev_path = devt_to_devpath(makedev(dev->disk.major,
|
|
|
7140c6 |
+ dev->disk.minor), 1, NULL);
|
|
|
7140c6 |
|
|
|
7140c6 |
struct sys_dev *hba2 = NULL;
|
|
|
7140c6 |
for (idev = intel_devices; idev; idev = idev->next) {
|
|
|
7140c6 |
@@ -11181,7 +11166,7 @@ static const char *imsm_get_disk_controller_domain(const char *path)
|
|
|
7140c6 |
struct sys_dev* hba;
|
|
|
7140c6 |
char *path;
|
|
|
7140c6 |
|
|
|
7140c6 |
- path = devt_to_devpath(st.st_rdev);
|
|
|
7140c6 |
+ path = devt_to_devpath(st.st_rdev, 1, NULL);
|
|
|
7140c6 |
if (path == NULL)
|
|
|
7140c6 |
return "unknown";
|
|
|
7140c6 |
hba = find_disk_attached_hba(-1, path);
|
|
|
7140c6 |
--
|
|
|
7140c6 |
2.7.5
|
|
|
7140c6 |
|