OSDN Git Service

Move SAS parsing to linux-sas.c
authorPeter Jones <pjones@redhat.com>
Wed, 6 Jun 2018 20:47:11 +0000 (16:47 -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-sas.c [new file with mode: 0644]
src/linux.c
src/linux.h

diff --git a/src/linux-sas.c b/src/linux-sas.c
new file mode 100644 (file)
index 0000000..4a11147
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ * 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 for SAS devices
+ *
+ * /sys/dev/block/$major:$minor looks like:
+ * 8:32 -> ../../devices/pci0000:00/0000:00:01.0/0000:01:00.0/host4/port-4:0/end_device-4:0/target4:0:0/4:0:0:0/block/sdc
+ * 8:33 -> ../../devices/pci0000:00/0000:00:01.0/0000:01:00.0/host4/port-4:0/end_device-4:0/target4:0:0/4:0:0:0/block/sdc/sdc1
+ *
+ * /sys/dev/block/8:32/device looks like:
+ * DUNNO.  But I suspect it's: ../../../4:0:0:0
+ *
+ * These things are also things in this case:
+ * /sys/class/scsi_host/host4/host_sas_address
+ * /sys/class/block/sdc/device/sas_address
+ *
+ * I'm not sure at the moment if they're the same or not.
+ */
+static ssize_t
+parse_sas(struct device *dev, const char *current)
+{
+        struct stat statbuf = { 0, };
+        int rc;
+        uint32_t scsi_host, scsi_bus, scsi_device, scsi_target;
+        uint64_t scsi_lun;
+        ssize_t pos;
+        uint8_t *filebuf = NULL;
+        uint64_t sas_address;
+
+        debug(DEBUG, "entry");
+
+        pos = parse_scsi_link(current, &scsi_host,
+                              &scsi_bus, &scsi_device,
+                              &scsi_target, &scsi_lun);
+        /*
+         * If we can't parse the scsi data, it isn't a sas device, so return 0
+         * not error.
+         */
+        if (pos < 0)
+                return 0;
+
+        /*
+         * Make sure it has the actual /SAS/ bits before we continue
+         * validating all this junk.
+         */
+        rc = sysfs_stat(&statbuf,
+                        "class/scsi_host/host%d/host_sas_address",
+                        scsi_host);
+        /*
+         * If we can't parse the scsi data, it isn't a /SAS/ device, so return
+         * 0 not error. Later errors mean it is an ata device, but we can't
+         * parse it right, so they return -1.
+         */
+        if (rc < 0)
+                return 0;
+
+        /*
+         * we also need to get the actual sas_address from someplace...
+         */
+        rc = read_sysfs_file(&filebuf,
+                             "class/block/%s/device/sas_address",
+                             dev->disk_name);
+        if (rc < 0 || filebuf == NULL)
+                return -1;
+
+        rc = sscanf((char *)filebuf, "%"PRIx64, &sas_address);
+        if (rc != 1)
+                return -1;
+
+        dev->sas_info.sas_address = sas_address;
+
+        dev->scsi_info.scsi_bus = scsi_bus;
+        dev->scsi_info.scsi_device = scsi_device;
+        dev->scsi_info.scsi_target = scsi_target;
+        dev->scsi_info.scsi_lun = scsi_lun;
+        dev->interface_type = sas;
+        return pos;
+}
+
+static ssize_t
+dp_create_sas(struct device *dev,
+              uint8_t *buf,  ssize_t size, ssize_t off)
+{
+        ssize_t sz;
+
+        debug(DEBUG, "entry");
+
+        sz = efidp_make_sas(buf + off, size ? size - off : 0,
+                            dev->sas_info.sas_address);
+
+        return sz;
+}
+
+enum interface_type sas_iftypes[] = { sas, unknown };
+
+struct dev_probe HIDDEN sas_parser = {
+        .name = "sas",
+        .iftypes = sas_iftypes,
+        .flags = DEV_PROVIDES_HD,
+        .parse = parse_sas,
+        .create = dp_create_sas,
+};
index 16c4680..97fcaf2 100644 (file)
@@ -214,38 +214,6 @@ sysfs_test_pmem(const char *buf)
        return 0;
 }
 
-static int
-sysfs_test_sas(const char *buf, ssize_t size)
-{
-       int rc;
-       char *path;
-       struct stat statbuf = { 0, };
-       char *newbuf;
-
-       int host;
-       int sz;
-
-       newbuf = strndupa(buf, size+1);
-       if (!newbuf)
-               return -1;
-       newbuf[size] = '\0';
-
-       errno = 0;
-       rc = sscanf(newbuf, "host%d/%n", &host, &sz);
-       if (rc < 1)
-               return (errno == 0) ? 0 : -1;
-
-       rc = asprintfa(&path, "/sys/class/scsi_host/host%d/host_sas_address",
-                       host);
-       if (rc < 0)
-               return -1;
-
-       rc = stat(path, &statbuf);
-       if (rc >= 0)
-               return 1;
-       return 0;
-}
-
 /* pmem12s -> ../devices/LNXSYSTM:00/LNXSYBUS:00/ACPI0012:00/ndbus0/region12/btt12.1/block/pmem12s
  * dev: 259:0
  * device -> ../../../btt12.1
@@ -291,128 +259,6 @@ sysfs_parse_pmem(uint8_t *buf,  ssize_t size, ssize_t *off,
 }
 
 static ssize_t
-sysfs_parse_sas(uint8_t *buf, ssize_t size, ssize_t *off,
-               const char *pbuf, ssize_t psize, ssize_t *poff,
-               struct disk_info *info)
-{
-       int rc;
-       int psz = 0;
-       uint8_t *filebuf = NULL;
-       uint64_t sas_address;
-
-       char *newpbuf;
-
-       newpbuf = strndupa(pbuf, psize+1);
-       if (!newpbuf)
-               return -1;
-       newpbuf[psize] = '\0';
-
-       *poff = 0;
-       *off = 0;
-
-       /* buf is:
-        * host4/port-4:0/end_device-4:0/target4:0:0/4:0:0:0/block/sdc/sdc1
-        */
-       uint32_t tosser0, tosser1, tosser2;
-
-       /* ignore a bunch of stuff
-        *    host4/port-4:0
-        * or host4/port-4:0:0
-        */
-       rc = sscanf(newpbuf+*poff, "host%d/port-%d:%d%n", &tosser0, &tosser1,
-                   &tosser2, &psz);
-       if (rc != 3)
-               return -1;
-       *poff += psz;
-
-       psz = 0;
-       rc = sscanf(pbuf+*poff, ":%d%n", &tosser0, &psz);
-       if (rc != 0 && rc != 1)
-               return -1;
-       *poff += psz;
-
-       /* next:
-        *    /end_device-4:0
-        * or /end_device-4:0:0
-        * awesomely these are the exact same fields that go into port-blah,
-        * but we don't care for now about any of them anyway.
-        */
-       rc = sscanf(newpbuf+*poff, "/end_device-%d:%d%n", &tosser0, &tosser1,
-                   &psz);
-       if (rc != 2)
-               return -1;
-       *poff += psz;
-
-       psz = 0;
-       rc = sscanf(newpbuf+*poff, ":%d%n", &tosser0, &psz);
-       if (rc != 0 && rc != 1)
-               return -1;
-       *poff += psz;
-
-       /* now:
-        * /target4:0:0/
-        */
-       uint64_t tosser3;
-       rc = sscanf(newpbuf+*poff, "/target%d:%d:%"PRIu64"/%n", &tosser0,
-                   &tosser1, &tosser3, &psz);
-       if (rc != 3)
-               return -1;
-       *poff += psz;
-
-       /* now:
-        * %d:%d:%d:%llu/
-        */
-       rc = sscanf(newpbuf+*poff, "%d:%d:%d:%"PRIu64"/%n",
-                   &info->sas_info.scsi_bus,
-                   &info->sas_info.scsi_device,
-                   &info->sas_info.scsi_target,
-                   &info->sas_info.scsi_lun, &psz);
-       if (rc != 4)
-               return -1;
-       *poff += psz;
-
-       /* what's left is:
-        * block/sdc/sdc1
-        */
-       char *disk_name = NULL;
-       char *part_name = NULL;
-       rc = sscanf(newpbuf+*poff, "block/%m[^/]/%m[^/]%n", &disk_name,
-                   &part_name, &psz);
-       if (rc != 2)
-               return -1;
-       *poff += psz;
-
-       /* check the original of this; it's guaranteed in our copy */
-       if (pbuf[*poff] != '\0') {
-               free(disk_name);
-               free(part_name);
-               errno = EINVAL;
-               return -1;
-       }
-
-       /*
-        * we also need to get the actual sas_address from someplace...
-        */
-       rc = read_sysfs_file(&filebuf,
-                            "class/block/%s/device/sas_address",
-                            disk_name);
-       if (rc < 0 || filebuf == NULL)
-               return -1;
-
-       rc = sscanf((char *)filebuf, "%"PRIx64, &sas_address);
-       if (rc != 1)
-               return -1;
-
-       info->sas_info.sas_address = sas_address;
-       info->disk_name = disk_name;
-       info->part_name = part_name;
-       info->interface_type = sas;
-
-       *off = efidp_make_sas(buf, size, sas_address);
-       return *off;
-}
-
-static ssize_t
 make_pci_path(uint8_t *buf, ssize_t size, char *pathstr, ssize_t *pathoff)
 {
        ssize_t off=0, sz=0;
@@ -597,31 +443,6 @@ make_blockdev_path(uint8_t *buf, ssize_t size, struct disk_info *info)
 
        }
 
-       /* /dev/sdc as SAS looks like:
-        * /sys/dev/block/8:32 -> ../../devices/pci0000:00/0000:00:01.0/0000:01:00.0/host4/port-4:0/end_device-4:0/target4:0:0/4:0:0:0/block/sdc
-        */
-       if (!found) {
-               rc = sysfs_test_sas(linkbuf+loff, PATH_MAX-off);
-               if (rc < 0)
-                       return -1;
-               else if (rc > 0) {
-                       ssize_t linksz=0;
-                       rc = sysfs_parse_sas(buf+off, size?size-off:0, &sz,
-                                            linkbuf+loff, PATH_MAX-off,
-                                            &linksz, info);
-                       if (rc < 0)
-                               return -1;
-                       /*
-                        * clang-analyzer complains about this because they
-                        * don't believe in writing code to avoid introducing
-                        * bugs later.
-                        */
-                       // loff += linksz;
-                       off += sz;
-                       found = 1;
-               }
-       }
-
        if (!found) {
                errno = ENOENT;
                return -1;
index 17f1586..60b72cf 100644 (file)
@@ -44,12 +44,12 @@ struct scsi_info {
 };
 
 struct sas_info {
-       uint32_t scsi_bus;
-       uint32_t scsi_device;
-       uint32_t scsi_target;
-       uint64_t scsi_lun;
+        uint32_t scsi_bus;
+        uint32_t scsi_device;
+        uint32_t scsi_target;
+        uint64_t scsi_lun;
 
-       uint64_t sas_address;
+        uint64_t sas_address;
 };
 
 struct sata_info {
@@ -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 sas_parser;
 extern struct dev_probe sata_parser;
 extern struct dev_probe nvme_parser;
 extern struct dev_probe virtblk_parser;