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

335 lines
11 KiB
Diff

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