Blame SOURCES/0004-imsm-add-generic-method-to-resolve-device-links.patch

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