OSDN Git Service

Move the PMEM device parser to linux-pmem.c
authorPeter Jones <pjones@redhat.com>
Wed, 6 Jun 2018 20:53:37 +0000 (16:53 -0400)
committerPeter Jones <pmjones@gmail.com>
Fri, 8 Jun 2018 19:11:37 +0000 (15:11 -0400)
This won't actually *work* yet, because the infrastructure to use it
(replacing "struct disk_info") won't land for a few more patches.

Signed-off-by: Peter Jones <pjones@redhat.com>
src/linux-pmem.c [new file with mode: 0644]
src/linux.c
src/linux.h

diff --git a/src/linux-pmem.c b/src/linux-pmem.c
new file mode 100644 (file)
index 0000000..503a591
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ * libefiboot - library for the manipulation of EFI boot variables
+ * Copyright 2012-2018 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 NVDIMM-P (pmem / btt) devices
+ * (does not include NVDIMM-${ANYTHING_ELSE})
+ *
+ * /sys/dev/block/$major:$minor looks like:
+ * 259:0 -> ../../devices/LNXSYSTM:00/LNXSYBUS:00/ACPI0012:00/ndbus0/region9/btt9.0/block/pmem9s
+ * 259:1 -> ../../devices/LNXSYSTM:00/LNXSYBUS:00/ACPI0012:00/ndbus0/region11/btt11.0/block/pmem11s
+ * 259:3 -> ../../devices/LNXSYSTM:00/LNXSYBUS:00/ACPI0012:00/ndbus0/region11/btt11.0/block/pmem11s/pmem11s1
+ *
+ * /sys/dev/block/259:0/device looks like:
+ * device -> ../../../btt9.0
+ * /sys/dev/block/259:1/device looks like:
+ * device -> ../../../btt11.0
+ *
+ * /sys/dev/block/259:1/partition looks like:
+ * $ cat partition
+ * 1
+ *
+ * /sys/dev/block/259:0/uuid looks like:
+ * $ cat uuid
+ * 6e54091e-7476-47ac-824b-b6dd69878661
+ *
+ * pmem12s -> ../devices/LNXSYSTM:00/LNXSYBUS:00/ACPI0012:00/ndbus0/region12/btt12.1/block/pmem12s
+ * dev: 259:0
+ * device -> ../../../btt12.1
+ * device/uuid: 0cee166e-dd56-4bc2-99d2-2544b69025b8
+ * 259:0 -> ../../devices/LNXSYSTM:00/LNXSYBUS:00/ACPI0012:00/ndbus0/region12/btt12.1/block/pmem12s
+ *
+ * pmem12.1s -> ../devices/LNXSYSTM:00/LNXSYBUS:00/ACPI0012:00/ndbus0/region12/btt12.2/block/pmem12.1s
+ * dev: 259:1
+ * device -> ../../../btt12.2
+ * device/uuid: 78d94521-91f7-47db-b3a7-51b764281940
+ * 259:1 -> ../../devices/LNXSYSTM:00/LNXSYBUS:00/ACPI0012:00/ndbus0/region12/btt12.2/block/pmem12.1s
+ *
+ * pmem12.2 -> ../devices/LNXSYSTM:00/LNXSYBUS:00/ACPI0012:00/ndbus0/region12/pfn12.1/block/pmem12.2
+ * dev: 259:2
+ * device -> ../../../pfn12.1
+ * device/uuid: 829c5205-89a5-4581-9819-df7d7754c622
+ * 259:2 -> ../../devices/LNXSYSTM:00/LNXSYBUS:00/ACPI0012:00/ndbus0/region12/pfn12.1/block/pmem12.2
+ */
+
+static ssize_t
+parse_pmem(struct device *dev, const char *current)
+{
+        uint8_t *filebuf = NULL;
+        uint8_t system, sysbus, acpi_id;
+        uint16_t pnp_id;
+        int ndbus, region, btt_region_id, btt_id, rc, pos;
+
+        debug(DEBUG, "entry");
+
+        if (!strcmp(dev->driver, "nd_pmem")) {
+                ;
+#if 0 /* dunno */
+        } else if (!strcmp(dev->driver, "nd_blk")) {
+                /* dunno */
+                dev->inteface_type = scsi;
+#endif
+        } else {
+                /*
+                 * not a pmem device
+                 */
+                return 0;
+        }
+
+        /*
+         * We're not actually using any of the values here except pos (our
+         * return value), but rather just being paranoid that this is the sort
+         * of device we care about.
+         *
+         * 259:0 -> ../../devices/LNXSYSTM:00/LNXSYBUS:00/ACPI0012:00/ndbus0/region12/btt12.1/block/pmem12s
+         */
+        rc = sscanf(current,
+                    "../../devices/LNXSYSTM:%hhx/LNXSYBUS:%hhx/ACPI%hx:%hhx/ndbus%d/region%d/btt%d.%d/%n",
+                    &system, &sysbus, &pnp_id, &acpi_id, &ndbus, &region,
+                    &btt_region_id, &btt_id, &pos);
+        if (rc < 8)
+                return 0;
+
+        /*
+         * but the UUID we really do need to have.
+         */
+        rc = read_sysfs_file(&filebuf,
+                             "class/block/%s/device/uuid", dev->disk_name);
+        if ((rc < 0 && errno == ENOENT) || filebuf == NULL)
+                return -1;
+
+        rc = efi_str_to_guid((char *)filebuf, &dev->nvdimm_label);
+        if (rc < 0)
+                return -1;
+
+        /* UUIDs are stored opposite Endian from GUIDs, so our normal GUID
+         * parser is giving us the wrong thing; swizzle those bytes around.
+         */
+        swizzle_guid_to_uuid(&dev->nvdimm_label);
+
+        dev->interface_type = nd_pmem;
+
+        return pos;
+}
+
+static ssize_t
+dp_create_pmem(struct device *dev,
+               uint8_t *buf, ssize_t size, ssize_t off)
+{
+        ssize_t sz;
+
+        debug(DEBUG, "entry");
+
+        sz = efidp_make_nvdimm(buf + off, size ? size - off : 0,
+                               &dev->nvdimm_label);
+
+        return sz;
+}
+
+enum interface_type pmem_iftypes[] = { nd_pmem, unknown };
+
+struct dev_probe HIDDEN pmem_parser = {
+        .name = "pmem",
+        .iftypes = pmem_iftypes,
+        .flags = DEV_PROVIDES_ROOT|DEV_PROVIDES_HD,
+        .parse = parse_pmem,
+        .create = dp_create_pmem,
+};
index 97fcaf2..2d3108e 100644 (file)
@@ -74,13 +74,7 @@ set_disk_and_part_name(struct disk_info *info)
         * If there's a better way to figure this out, it'd be good, because
         * I don't want to have to change this for every new disk type...
         */
-       if (!strncmp(ultimate, "pmem", 4)) {
-               if (!info->disk_name) {
-                       info->disk_name = strdup(ultimate);
-                       if (!info->disk_name)
-                               return -1;
-               }
-       } else if (!strcmp(penultimate, "block")) {
+        if (!strcmp(penultimate, "block")) {
                if (!info->disk_name) {
                        info->disk_name = strdup(ultimate);
                        if (!info->disk_name)
@@ -193,71 +187,6 @@ find_parent_devpath(const char * const child, char **parent)
        return 0;
 }
 
-/* NVDIMM-P paths */
-static int
-sysfs_test_pmem(const char *buf)
-{
-       char *driverbuf = NULL;
-       int rc;
-
-       rc = sysfs_readlink(&driverbuf,
-                           "dev/block/%s/device/driver", buf);
-       if (rc < 0 || !driverbuf)
-               return 0;
-
-       char *driver = strrchr(driverbuf, '/');
-       if (!driver || !*driver)
-               return -1;
-       driver+=1;
-       if (!strcmp(driver, "nd_pmem"))
-               return 1;
-       return 0;
-}
-
-/* pmem12s -> ../devices/LNXSYSTM:00/LNXSYBUS:00/ACPI0012:00/ndbus0/region12/btt12.1/block/pmem12s
- * dev: 259:0
- * device -> ../../../btt12.1
- * device/uuid: 0cee166e-dd56-4bc2-99d2-2544b69025b8
- * 259:0 -> ../../devices/LNXSYSTM:00/LNXSYBUS:00/ACPI0012:00/ndbus0/region12/btt12.1/block/pmem12s
- *
- * pmem12.1s -> ../devices/LNXSYSTM:00/LNXSYBUS:00/ACPI0012:00/ndbus0/region12/btt12.2/block/pmem12.1s
- * dev: 259:1
- * device -> ../../../btt12.2
- * device/uuid: 78d94521-91f7-47db-b3a7-51b764281940
- * 259:1 -> ../../devices/LNXSYSTM:00/LNXSYBUS:00/ACPI0012:00/ndbus0/region12/btt12.2/block/pmem12.1s
- *
- * pmem12.2 -> ../devices/LNXSYSTM:00/LNXSYBUS:00/ACPI0012:00/ndbus0/region12/pfn12.1/block/pmem12.2
- * dev: 259:2
- * device -> ../../../pfn12.1
- * device/uuid: 829c5205-89a5-4581-9819-df7d7754c622
- * 259:2 -> ../../devices/LNXSYSTM:00/LNXSYBUS:00/ACPI0012:00/ndbus0/region12/pfn12.1/block/pmem12.2
- */
-static ssize_t
-sysfs_parse_pmem(uint8_t *buf,  ssize_t size, ssize_t *off,
-                 const char *pbuf, ssize_t psize UNUSED,
-                 ssize_t *poff UNUSED, struct disk_info *info)
-{
-       uint8_t *filebuf = NULL;
-       int rc;
-
-       rc = read_sysfs_file(&filebuf,
-                            "class/block/%s/device/uuid", pbuf);
-       if ((rc < 0 && errno == ENOENT) || filebuf == NULL)
-               return -1;
-
-       rc = efi_str_to_guid((char *)filebuf, &info->nvdimm_label);
-       if (rc < 0)
-               return -1;
-
-       /* UUIDs are stored opposite Endian from GUIDs, so our normal GUID
-        * parser is giving us the wrong thing; swizzle those bytes around.
-        */
-       swizzle_guid_to_uuid(&info->nvdimm_label);
-
-       *off = efidp_make_nvdimm(buf, size, &info->nvdimm_label);
-       return *off;
-}
-
 static ssize_t
 make_pci_path(uint8_t *buf, ssize_t size, char *pathstr, ssize_t *pathoff)
 {
@@ -388,28 +317,6 @@ make_blockdev_path(uint8_t *buf, ssize_t size, struct disk_info *info)
                return -1;
        }
 
-       /*
-        * the sysfs path basically looks like one of:
-        * ../../devices/pci$PCI_STUFF/$BLOCKDEV_STUFF/block/$DISK/$PART
-        * ../../devices/LNXSYSTM:00/LNXSYBUS:00/ACPI0012:00/ndbus0/region12/btt12.1/block/pmem12s
-        */
-       rc = sysfs_test_pmem(linkbuf+loff);
-       if (rc < 0) {
-               efi_error("sysfs_test_pmem(\"%s\") failed", linkbuf+loff);
-               return -1;
-       } else if (rc > 0) {
-               ssize_t linksz=0;
-               info->interface_type = nd_pmem;
-               rc = sysfs_parse_pmem(buf+off, size?size-off:0, &sz,
-                                     linkbuf+loff, PATH_MAX-off,
-                                     &linksz, info);
-               if (rc < 0)
-                       return -1;
-               loff += linksz;
-               off += sz;
-               found = 1;
-       }
-
        if (!found) {
                rc = sscanf(linkbuf+loff, "../../devices/%n", &lsz);
                if (rc != 0) {
@@ -455,7 +362,6 @@ int HIDDEN
 eb_disk_info_from_fd(int fd, struct disk_info *info)
 {
        struct stat buf;
-       char *driver;
        int rc;
 
        memset(info, 0, sizeof *info);
@@ -480,23 +386,6 @@ eb_disk_info_from_fd(int fd, struct disk_info *info)
                return 1;
        }
 
-       rc = sysfs_readlink(&driver, "dev/block/%"PRIu64":%"PRIu32"/device/driver",
-                           info->major, info->minor);
-       if (rc > 0) {
-               char *last = strrchr(driver, '/');
-               if (last) {
-                       if (!strcmp(last+1, "nd_pmem")) {
-                               info->interface_type = nd_pmem;
-                               return 0;
-#if 0 /* dunno */
-                       } else if (!strcmp(last+1, "nd_blk")) {
-                               /* dunno */
-                               info->inteface_type = scsi;
-#endif
-                       }
-               }
-       }
-
        errno = ENOSYS;
        return -1;
 }
index 6cf470f..3d6f156 100644 (file)
@@ -259,6 +259,7 @@ extern ssize_t parse_scsi_link(const char *current, uint32_t *host,
 #define set_part(x, y) /* XXX remove later */
 
 /* device support implementations */
+extern struct dev_probe pmem_parser;
 extern struct dev_probe pci_parser;
 extern struct dev_probe sas_parser;
 extern struct dev_probe sata_parser;