Blame SOURCES/0057-Handle-sys-devices-virtual-nvme-fabrics-nvme-subsyst.patch

d5c737
From ad1d30fc5e20b933b6ad59d35c13e0193cd68a2d Mon Sep 17 00:00:00 2001
d5c737
From: Peter Jones <pjones@redhat.com>
d5c737
Date: Wed, 2 Oct 2019 17:04:12 -0400
d5c737
Subject: [PATCH 57/63] Handle
d5c737
 /sys/devices/virtual/{nvme-fabrics,nvme-subsystem} devices
d5c737
d5c737
Signed-off-by: Peter Jones <pjones@redhat.com>
d5c737
---
d5c737
 src/linux-nvme.c         | 59 ++++++++++++++++++++++-----
d5c737
 src/linux-virtual-root.c | 88 ++++++++++++++++++++++++++++++++++++++++
d5c737
 src/linux.c              | 43 +++++++++++++++++---
d5c737
 src/linux.h              |  4 +-
d5c737
 4 files changed, 176 insertions(+), 18 deletions(-)
d5c737
 create mode 100644 src/linux-virtual-root.c
d5c737
d5c737
diff --git a/src/linux-nvme.c b/src/linux-nvme.c
d5c737
index 455c4c7ba9b..7ca2fa3c283 100644
d5c737
--- a/src/linux-nvme.c
d5c737
+++ b/src/linux-nvme.c
d5c737
@@ -1,6 +1,6 @@
d5c737
 /*
d5c737
  * libefiboot - library for the manipulation of EFI boot variables
d5c737
- * Copyright 2012-2018 Red Hat, Inc.
d5c737
+ * Copyright 2012-2019 Red Hat, Inc.
d5c737
  *
d5c737
  * This library is free software; you can redistribute it and/or
d5c737
  * modify it under the terms of the GNU Lesser General Public License as
d5c737
@@ -15,7 +15,6 @@
d5c737
  * You should have received a copy of the GNU Lesser General Public
d5c737
  * License along with this library; if not, see
d5c737
  * <http://www.gnu.org/licenses/>.
d5c737
- *
d5c737
  */
d5c737
 
d5c737
 #include "fix_coverity.h"
d5c737
@@ -24,6 +23,7 @@
d5c737
 #include <fcntl.h>
d5c737
 #include <inttypes.h>
d5c737
 #include <stdint.h>
d5c737
+#include <sys/param.h>
d5c737
 #include <unistd.h>
d5c737
 
d5c737
 #include "efiboot.h"
d5c737
@@ -34,6 +34,12 @@
d5c737
  * /sys/dev/block/$major:$minor looks like:
d5c737
  * 259:0 -> ../../devices/pci0000:00/0000:00:1d.0/0000:05:00.0/nvme/nvme0/nvme0n1
d5c737
  * 259:1 -> ../../devices/pci0000:00/0000:00:1d.0/0000:05:00.0/nvme/nvme0/nvme0n1/nvme0n1p1
d5c737
+ * or:
d5c737
+ * 259:0 ->../../devices/virtual/nvme-fabrics/ctl/nvme0/nvme0n1
d5c737
+ * 259:1 ->../../devices/virtual/nvme-fabrics/ctl/nvme0/nvme0n1/nvme0n1p1
d5c737
+ * or:
d5c737
+ * 259:5 -> ../../devices/virtual/nvme-subsystem/nvme-subsys0/nvme0n1
d5c737
+ * 259:6 -> ../../devices/virtual/nvme-subsystem/nvme-subsys0/nvme0n1/nvme0n1p1
d5c737
  *
d5c737
  * /sys/dev/block/259:0/device looks like:
d5c737
  * device -> ../../nvme0
d5c737
@@ -53,17 +59,44 @@ parse_nvme(struct device *dev, const char *current, const char *root UNUSED)
d5c737
 	int rc;
d5c737
 	int32_t tosser0, tosser1, tosser2, ctrl_id, ns_id, partition;
d5c737
 	uint8_t *filebuf = NULL;
d5c737
+	int pos0 = -1, pos1 = -1, pos2 = -1;
d5c737
 	ssize_t sz = 0;
d5c737
-	int pos0 = 0, pos1 = 0;
d5c737
+	struct subdir {
d5c737
+		const char * const name;
d5c737
+		const char * const fmt;
d5c737
+		int *pos0, *pos1;
d5c737
+	} subdirs[] = {
d5c737
+		{"nvme-subsysN/", "%nnvme-subsys%d/%n", &pos0, &pos2},
d5c737
+		{"ctl/", "%nctl/%n%n", &pos0, &pos1},
d5c737
+		{"nvme/", "%nnvme/%n%n", &pos0, &pos1},
d5c737
+		{NULL, }
d5c737
+	};
d5c737
 
d5c737
 	debug("entry");
d5c737
 
d5c737
-	debug("searching for nvme/nvme0/nvme0n1 or nvme/nvme0/nvme0n1/nvme0n1p1");
d5c737
-	rc = sscanf(current, "nvme/nvme%d/nvme%dn%d%n/nvme%dn%dp%d%n",
d5c737
-	            &tosser0, &ctrl_id, &ns_id, &pos0,
d5c737
-	            &tosser1, &tosser2, &partition, &pos1);
d5c737
-	debug("current:'%s' rc:%d pos0:%d pos1:%d\n", current, rc, pos0, pos1);
d5c737
-	dbgmk("         ", pos0, pos1);
d5c737
+	/*
d5c737
+	 * in this case, *any* of these is okay.
d5c737
+	 */
d5c737
+	for (int i = 0; subdirs[i].name; i++) {
d5c737
+		debug("searching for %s", subdirs[i].name);
d5c737
+		pos0 = tosser0 = pos1 = -1;
d5c737
+		rc = sscanf(current, subdirs[i].fmt, &pos0, &pos1, &pos2);
d5c737
+		debug("current:'%s' rc:%d pos0:%d pos1:%d\n", current, rc,
d5c737
+		      *subdirs[i].pos0, *subdirs[i].pos1);
d5c737
+		dbgmk("         ", *subdirs[i].pos0, *subdirs[i].pos1);
d5c737
+		if (*subdirs[i].pos0 >= 0 && *subdirs[i].pos1 >= *subdirs[i].pos0) {
d5c737
+			sz += *subdirs[i].pos1;
d5c737
+			current += *subdirs[i].pos1;
d5c737
+			break;
d5c737
+		}
d5c737
+	}
d5c737
+
d5c737
+	debug("searching for nvme0/nvme0n1 or nvme0/nvme0n1/nvme0n1p1");
d5c737
+	rc = sscanf(current, "%nnvme%d/nvme%dn%d%n/nvme%dn%dp%d%n",
d5c737
+	            &pos0, &tosser0, &ctrl_id, &ns_id, &pos1,
d5c737
+	            &tosser1, &tosser2, &partition, &pos2);
d5c737
+	debug("current:'%s' rc:%d pos0:%d pos1:%d pos2:%d\n", current, rc, pos0, pos1, pos2);
d5c737
+	dbgmk("         ", pos0, MAX(pos1,pos2));
d5c737
 	/*
d5c737
 	 * If it isn't of that form, it's not one of our nvme devices.
d5c737
 	 */
d5c737
@@ -79,14 +112,15 @@ parse_nvme(struct device *dev, const char *current, const char *root UNUSED)
d5c737
 	        if (dev->part == -1)
d5c737
 	                dev->part = partition;
d5c737
 
d5c737
-	        pos0 = pos1;
d5c737
+		pos1 = pos2;
d5c737
 	}
d5c737
 
d5c737
-	sz += pos0;
d5c737
+	sz += pos1;
d5c737
 
d5c737
 	/*
d5c737
 	 * now fish the eui out of sysfs is there is one...
d5c737
 	 */
d5c737
+	debug("looking for the eui");
d5c737
 	char *euipath = NULL;
d5c737
 	rc = read_sysfs_file(&filebuf, "class/block/nvme%dn%d/eui", ctrl_id, ns_id);
d5c737
 	if (rc < 0 && (errno == ENOENT || errno == ENOTDIR)) {
d5c737
@@ -109,6 +143,9 @@ parse_nvme(struct device *dev, const char *current, const char *root UNUSED)
d5c737
 	                errno = EINVAL;
d5c737
 	                return -1;
d5c737
 	        }
d5c737
+		debug("eui is %02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
d5c737
+		      eui[0], eui[1], eui[2], eui[3],
d5c737
+		      eui[4], eui[5], eui[6], eui[7]);
d5c737
 	        dev->nvme_info.has_eui = 1;
d5c737
 	        memcpy(dev->nvme_info.eui, eui, sizeof(eui));
d5c737
 	}
d5c737
diff --git a/src/linux-virtual-root.c b/src/linux-virtual-root.c
d5c737
new file mode 100644
d5c737
index 00000000000..b2d36b4095f
d5c737
--- /dev/null
d5c737
+++ b/src/linux-virtual-root.c
d5c737
@@ -0,0 +1,88 @@
d5c737
+/*
d5c737
+ * libefiboot - library for the manipulation of EFI boot variables
d5c737
+ * Copyright 2012-2019 Red Hat, Inc.
d5c737
+ *
d5c737
+ * This library is free software; you can redistribute it and/or
d5c737
+ * modify it under the terms of the GNU Lesser General Public License as
d5c737
+ * published by the Free Software Foundation; either version 2.1 of the
d5c737
+ * License, or (at your option) any later version.
d5c737
+ *
d5c737
+ * This library is distributed in the hope that it will be useful,
d5c737
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
d5c737
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
d5c737
+ * Lesser General Public License for more details.
d5c737
+ *
d5c737
+ * You should have received a copy of the GNU Lesser General Public
d5c737
+ * License along with this library; if not, see
d5c737
+ * <http://www.gnu.org/licenses/>.
d5c737
+ */
d5c737
+
d5c737
+#include "fix_coverity.h"
d5c737
+
d5c737
+#include <errno.h>
d5c737
+#include <fcntl.h>
d5c737
+#include <inttypes.h>
d5c737
+#include <stdint.h>
d5c737
+#include <unistd.h>
d5c737
+
d5c737
+#include "efiboot.h"
d5c737
+
d5c737
+/*
d5c737
+ * Support virtually rooted devices (fibre+nvme, etc.)
d5c737
+ *
d5c737
+ * /sys/dev/block/$major:$minor looks like:
d5c737
+ * 259:0 ->../../devices/virtual/nvme-fabrics/ctl/nvme0/nvme0n1
d5c737
+ * 259:1 ->../../devices/virtual/nvme-fabrics/ctl/nvme0/nvme0n1/nvme0n1p1
d5c737
+ * or:
d5c737
+ * 259:5 -> ../../devices/virtual/nvme-subsystem/nvme-subsys0/nvme0n1
d5c737
+ * 259:6 -> ../../devices/virtual/nvme-subsystem/nvme-subsys0/nvme0n1/nvme0n1p1
d5c737
+ */
d5c737
+
d5c737
+static ssize_t
d5c737
+parse_virtual_root(struct device *dev UNUSED, const char *current, const char *root UNUSED)
d5c737
+{
d5c737
+	int rc;
d5c737
+	ssize_t sz;
d5c737
+	int pos0 = 0, pos1 = 0;
d5c737
+	struct subdir {
d5c737
+		const char * const name;
d5c737
+		const char * const fmt;
d5c737
+	} subdirs[] = {
d5c737
+		{"../../devices/virtual", "%n../../devices/virtual/%n"},
d5c737
+		{"nvme-subsystem/", "%nnvme-subsystem/%n"},
d5c737
+		{"nvme-fabrics/ctl/", "%nnvme-fabrics/ctl/%n"},
d5c737
+		{NULL, NULL}
d5c737
+	};
d5c737
+
d5c737
+	debug("entry");
d5c737
+
d5c737
+	for (int i = 0; subdirs[i].name; i++) {
d5c737
+		debug("searching for %s", subdirs[i].name);
d5c737
+		pos0 = pos1 = -1;
d5c737
+		rc = sscanf(current, subdirs[i].fmt, &pos0, &pos1);
d5c737
+		debug("current:'%s' rc:%d pos0:%d pos1:%d\n", current, rc, pos0, pos1);
d5c737
+		dbgmk("        ", pos0, pos1);
d5c737
+		if (rc == 1) {
d5c737
+			sz += pos1;
d5c737
+			current += pos1;
d5c737
+			if (i > 0)
d5c737
+				goto found;
d5c737
+		}
d5c737
+	}
d5c737
+
d5c737
+	sz = 0;
d5c737
+found:
d5c737
+	debug("current:'%s' sz:%zd\n", current, sz);
d5c737
+	return sz;
d5c737
+}
d5c737
+
d5c737
+static enum interface_type virtual_root_iftypes[] = { virtual_root, unknown };
d5c737
+
d5c737
+struct dev_probe HIDDEN virtual_root_parser = {
d5c737
+	.name = "virtual_root",
d5c737
+	.iftypes = virtual_root_iftypes,
d5c737
+	.flags = DEV_ABBREV_ONLY|DEV_PROVIDES_ROOT,
d5c737
+	.parse = parse_virtual_root,
d5c737
+};
d5c737
+
d5c737
+// vim:fenc=utf-8:tw=75:noet
d5c737
diff --git a/src/linux.c b/src/linux.c
d5c737
index 30db22d95dd..7dd8d4cd858 100644
d5c737
--- a/src/linux.c
d5c737
+++ b/src/linux.c
d5c737
@@ -170,16 +170,17 @@ int HIDDEN
d5c737
 set_disk_and_part_name(struct device *dev)
d5c737
 {
d5c737
 	int rc = -1;
d5c737
-
d5c737
-	/*
d5c737
-	 * results are like such:
d5c737
-	 * maj:min -> ../../devices/pci$PCI_STUFF/$BLOCKDEV_STUFF/block/$DISK/$PART
d5c737
-	 */
d5c737
-
d5c737
 	char *ultimate = pathseg(dev->link, -1);
d5c737
 	char *penultimate = pathseg(dev->link, -2);
d5c737
 	char *approximate = pathseg(dev->link, -3);
d5c737
 	char *proximate = pathseg(dev->link, -4);
d5c737
+	char *psl5 = pathseg(dev->link, -5);
d5c737
+
d5c737
+
d5c737
+	/*
d5c737
+	 * devlinks look something like:
d5c737
+	 * maj:min -> ../../devices/pci$PCI_STUFF/$BLOCKDEV_STUFF/block/$DISK/$PART
d5c737
+	 */
d5c737
 
d5c737
 	errno = 0;
d5c737
 	debug("dev->disk_name:%p dev->part_name:%p", dev->disk_name, dev->part_name);
d5c737
@@ -188,6 +189,7 @@ set_disk_and_part_name(struct device *dev)
d5c737
 	debug("penultimate:'%s'", penultimate ? : "");
d5c737
 	debug("approximate:'%s'", approximate ? : "");
d5c737
 	debug("proximate:'%s'", proximate ? : "");
d5c737
+	debug("psl5:'%s'", psl5 ? : "");
d5c737
 
d5c737
 	if (ultimate && penultimate &&
d5c737
 	    ((proximate && !strcmp(proximate, "nvme")) ||
d5c737
@@ -232,6 +234,34 @@ set_disk_and_part_name(struct device *dev)
d5c737
 	        set_disk_name(dev, "%s", ultimate);
d5c737
 	        debug("disk:%s", ultimate);
d5c737
 		rc = 0;
d5c737
+	} else if ((proximate && ultimate && !strcmp(proximate, "nvme-fabrics")) ||
d5c737
+		    (approximate && ultimate && !strcmp(approximate, "nvme-subsystem"))) {
d5c737
+		/*
d5c737
+		 * 259:0 ->../../devices/virtual/nvme-fabrics/ctl/nvme0/nvme0n1
d5c737
+		 *				 ^ proximate            ^ ultimate
d5c737
+		 * or
d5c737
+		 * 259:5 -> ../../devices/virtual/nvme-subsystem/nvme-subsys0/nvme0n1
d5c737
+		 *                                ^ approximate  ^ penultimate
d5c737
+		 *                                                   ultimate ^
d5c737
+		 */
d5c737
+		set_disk_name(dev, "%s", ultimate);
d5c737
+		debug("disk:%s", ultimate);
d5c737
+		rc = 0;
d5c737
+	} else if ((psl5 && penultimate && ultimate && !strcmp(psl5, "nvme-fabrics")) ||
d5c737
+		   (proximate && penultimate && ultimate && !strcmp(proximate, "nvme-subsystem"))) {
d5c737
+		/*
d5c737
+		 * 259:1 -> ../../devices/virtual/nvme-fabrics/ctl/nvme0/nvme0n1/nvme0n1p1
d5c737
+		 *                                ^psl5                  ^ penultimate
d5c737
+		 *                                                      ultimate ^
d5c737
+		 * or
d5c737
+		 * 259:6 -> ../../devices/virtual/nvme-subsystem/nvme-subsys0/nvme0n1/nvme0n1p1
d5c737
+		 *                                ^ proximate                 ^ penultimate
d5c737
+		 *                                                           ultimate ^
d5c737
+		 */
d5c737
+		set_disk_name(dev, "%s", penultimate);
d5c737
+		set_part_name(dev, "%s", ultimate);
d5c737
+		debug("disk:%s part:%s", penultimate, ultimate);
d5c737
+		rc = 0;
d5c737
 	}
d5c737
 
d5c737
 	if (rc < 0)
d5c737
@@ -248,6 +278,7 @@ static struct dev_probe *dev_probes[] = {
d5c737
 	&acpi_root_parser,
d5c737
 	&pci_root_parser,
d5c737
 	&soc_root_parser,
d5c737
+	&virtual_root_parser,
d5c737
 	&pci_parser,
d5c737
 	&virtblk_parser,
d5c737
 	&sas_parser,
d5c737
diff --git a/src/linux.h b/src/linux.h
d5c737
index ae9835ef7ce..6bfc5869254 100644
d5c737
--- a/src/linux.h
d5c737
+++ b/src/linux.h
d5c737
@@ -99,7 +99,8 @@ struct emmc_info {
d5c737
 
d5c737
 enum interface_type {
d5c737
 	unknown,
d5c737
-	isa, acpi_root, pci_root, soc_root, pci, network,
d5c737
+	isa, acpi_root, pci_root, soc_root, virtual_root,
d5c737
+	pci, network,
d5c737
 	ata, atapi, scsi, sata, sas,
d5c737
 	usb, i1394, fibre, i2o,
d5c737
 	md, virtblk,
d5c737
@@ -346,6 +347,7 @@ extern struct dev_probe pmem_parser;
d5c737
 extern struct dev_probe pci_root_parser;
d5c737
 extern struct dev_probe acpi_root_parser;
d5c737
 extern struct dev_probe soc_root_parser;
d5c737
+extern struct dev_probe virtual_root_parser;
d5c737
 extern struct dev_probe pci_parser;
d5c737
 extern struct dev_probe sas_parser;
d5c737
 extern struct dev_probe sata_parser;
d5c737
-- 
d5c737
2.26.2
d5c737