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

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