On Mon, 2015-10-05 at 12:35 +0200, Johannes Thumshirn wrote:
> Add sysfs_hba to to fcoemon_utils. This is the 1st part of obsoleting
> libHBAAPI2 and libhbalinux2 for fcoe-utils.
>
> Signed-off-by: Johannes Thumshirn <[email protected]>
> ---
> Makefile.am | 7 +-
> configure.ac | 3 +
> fcoe-utils.spec.in | 2 +-
> include/sysfs_hba.h | 62 ++++++++
> lib/sysfs_hba.c | 426
> ++++++++++++++++++++++++++++++++++++++++++++++++++++
> 5 files changed, 496 insertions(+), 4 deletions(-)
> create mode 100644 include/sysfs_hba.h
> create mode 100644 lib/sysfs_hba.c
>
> diff --git a/Makefile.am b/Makefile.am
> index c6599ef..59c197d 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -9,7 +9,7 @@ AM_CFLAGS = -Wall -Wformat=2 -Werror -Wmissing-prototypes
> -Wstrict-prototypes
>
> ## rules for building fcoeadm
> fcoeadm_SOURCES = fcoeadm.c fcoeadm_display.c
> -fcoeadm_LDADD = lib/libutil.a libopenfcoe.a $(HBAAPI_LIBS)
> +fcoeadm_LDADD = lib/libutil.a libopenfcoe.a $(PCIACCESS_LIBS) $(HBAAPI_LIBS)
> fcoeadm_CFLAGS = $(AM_CFLAGS) $(HBAAPI_CFLAGS)
>
> ## rules for building fcoemon
> @@ -29,7 +29,8 @@ fipvlan_LDADD = lib/libutil.a
> AUTOMAKE_OPTIONS=subdir-objects
> noinst_LIBRARIES = lib/libutil.a libopenfcoe.a
> lib_libutil_a_SOURCES = lib/fcoe_utils.c lib/sa_log.c lib/sa_select.c \
> - lib/sa_timer.c lib/sa_other.c lib/fip.c lib/rtnetlink.c lib/sa_sys.c
> + lib/sa_timer.c lib/sa_other.c lib/fip.c lib/rtnetlink.c lib/sa_sys.c \
> + lib/sysfs_hba.c
> libopenfcoe_a_SOURCES = libopenfcoe.c
>
> ## header files that need to be distributed
> @@ -38,7 +39,7 @@ noinst_HEADERS = fcoeadm_display.h fcoe_clif.h fcoemon.h \
> include/fc_types.h include/fip.h include/net_types.h
> include/rtnetlink.h \
> include/libopenfcoe.h include/scsi_netlink_fc.h include/scsi_netlink.h \
> include/strarr.h include/fc_ns.h include/fc_gs.h include/fc_els.h
> include/scsi_bsg_fc.h \
> - include/linux/rtnetlink.h include/linux/types.h include/linux/dcbnl.h
> + include/sysfs_hba.h include/linux/rtnetlink.h include/linux/types.h
> include/linux/dcbnl.h
>
> ## install configuration file in $(prefix)/etc/fcoe
> fcoe_configdir = ${sysconfdir}/fcoe
> diff --git a/configure.ac b/configure.ac
> index ef0ffb1..5bafef3 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -17,6 +17,9 @@ AC_SUBST([LLDPAD_CFLAGS])
> PKG_CHECK_MODULES([LIBHBALINUX], [libhbalinux >= 1.0.17])
> AC_SUBST([LIBHBALINUX_CFLAGS])
>
> +PKG_CHECK_MODULES([PCIACCESS], [pciaccess])
> +AC_SUBST([PCIACCESS_LIBS])
> +
> PKG_PROG_PKG_CONFIG
> AC_ARG_WITH([systemdsystemunitdir],
> AS_HELP_STRING([--with-systemdsystemunitdir=DIR],
> diff --git a/fcoe-utils.spec.in b/fcoe-utils.spec.in
> index d45b84b..dff3fbd 100644
> --- a/fcoe-utils.spec.in
> +++ b/fcoe-utils.spec.in
> @@ -9,7 +9,7 @@ URL: http://www.open-fcoe.org
> Source0: http://www.open-fcoe.org/openfc/%{name}-%{version}.tar.gz
> BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u}
> -n)
>
> -BuildRequires: libHBAAPI-devel lldpad-devel
> +BuildRequires: libHBAAPI-devel lldpad-devel libpciaccess0
> Requires: lldpad
> Requires(post): chkconfig
> Requires(preun): chkconfig initscripts
> diff --git a/include/sysfs_hba.h b/include/sysfs_hba.h
> new file mode 100644
> index 0000000..3038813
> --- /dev/null
> +++ b/include/sysfs_hba.h
> @@ -0,0 +1,62 @@
> +/*
> + * Copyright(c) 2015 SUSE GmbH. All rights reserved.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
> + * more details.
> + *
> + * Maintained at www.Open-FCoE.org
> + */
> +
> +#ifndef _SYSFS_HBA_H
> +#define _SYSFS_HBA_H
> +
> +#include <stdint.h>
> +
> +#define SYSFS_HOST_DIR "/sys/class/fc_host"
> +#define SYSFS_NET_DIR "/sys/class/net"
> +
> +#define HBA_PORTSPEED_4GBIT 0x0008 /* 4 GBit/sec */
> +#define HBA_PORTSPEED_8GBIT 0x0010 /* 8 GBit/sec */
> +#define HBA_PORTSPEED_16GBIT 0x0020 /* 16 GBit/sec */
> +#define HBA_PORTSPEED_32GBIT 0x0040 /* 32 GBit/sec */
> +#define HBA_PORTSPEED_20GBIT 0x0080 /* 20 GBit/sec */
> +#define HBA_PORTSPEED_40GBIT 0x0100 /* 40 GBit/sec */
> +#define HBA_PORTSPEED_NOT_NEGOTIATED (1 << 15) /* Speed not established */
> +
> +struct port_attributes {
> + char device_name[256];
> + char symbolic_name[256];
> + char node_name[256];
> + char port_name[256];
> + char fabric_name[256];
> + char speed[256];
> + char supported_speeds[256];
> + char maxframe_size[256];
> + char port_id[256];
> + char port_state[256];
> +};
> +
> +struct hba_info {
> + char manufacturer[64];
> + char serial_number[64];
> + char model_description[256];
> + char hardware_version[256];
> + char driver_name[256];
> + char driver_version[256];
> + uint32_t nports;
> +};
> +
> +
> +int get_number_of_adapters(void);
> +struct hba_info *get_hbainfo_by_pcidev(const char *pcidev);
> +struct port_attributes *get_port_attribs(const char *host);
> +char *get_pci_dev_from_netdev(const char *netdev);
> +char *get_host_from_netdev(const char *netdev);
> +
> +#endif /* _SYSFS_HBA_H */
> diff --git a/lib/sysfs_hba.c b/lib/sysfs_hba.c
> new file mode 100644
> index 0000000..b774361
> --- /dev/null
> +++ b/lib/sysfs_hba.c
> @@ -0,0 +1,426 @@
> +/*
> + * Copyright(c) 2015 SUSE GmbH. All rights reserved.
I see mostly libhbalinux/pci.c code moved here and then new code from
you, it is good consolidation under single file but then original
Copyright needs to carried forward here as:-
"* Copyright (c) 2008, Intel Corporation."
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
> + * more details.
> + *
> + * Maintained at www.Open-FCoE.org
> + */
> +
> +#define _GNU_SOURCE
> +
> +#include <linux/pci_regs.h>
> +#include <sys/types.h>
> +#include <sys/stat.h>
> +#include <dirent.h>
> +#include <errno.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <stdio.h>
> +#include <stdint.h>
> +#include <inttypes.h>
> +#include <unistd.h>
> +#include <pciaccess.h>
> +
> +#include "sysfs_hba.h"
> +#include "fcoemon_utils.h"
> +
> +static void get_device_serial_number(struct pci_device *dev,
> + struct hba_info *info)
> +{
> + uint32_t pcie_cap_header;
> + uint32_t dword_high = 0;
> + uint32_t dword_low = 0;
> + uint16_t pcie_cap_id;
> + pciaddr_t offset;
> + uint16_t status;
> + uint8_t cap_ptr;
> + int rc;
> +
> + /* Default */
> + snprintf(info->serial_number, sizeof(info->serial_number), "Unknown");
> +
> + /*
> + * Read the Status Regiser in the PCIe configuration
> + * header space to see if the PCI Capability List is
> + * supported by this device.
> + */
> + rc = pci_device_cfg_read_u16(dev, &status, PCI_STATUS);
> + if (rc) {
> + fprintf(stderr, "Failed reading PCI status register\n");
> + return;
> + }
> +
> + if (!(status & PCI_STATUS_CAP_LIST)) {
> + fprintf(stderr, "PCI capabilities are not supported\n");
> + return;
> + }
> +
> + /*
> + * Read the offset (cap_ptr) of first entry in the capability list in
> + * the PCI configuration space.
> + */
> + rc = pci_device_cfg_read_u8(dev, &cap_ptr, PCI_CAPABILITY_LIST);
> + if (rc) {
> + fprintf(stderr,
> + "Failed reading PCI Capability List Register\n");
> + return;
> + }
> + offset = cap_ptr;
> +
> + /* Search for the PCIe capability */
> + while (offset) {
> + uint8_t next_cap;
> + uint8_t cap_id;
> +
> + rc = pci_device_cfg_read_u8(dev, &cap_id,
> + offset + PCI_CAP_LIST_ID);
> + if (rc) {
> + fprintf(stderr,
> + "Failed reading capability ID at 0x%"PRIx64"\n",
> + offset + PCI_CAP_LIST_ID);
> + return;
> + }
> +
> + if (cap_id != PCI_CAP_ID_EXP) {
> + rc = pci_device_cfg_read_u8(dev, &next_cap,
> + offset + PCI_CAP_LIST_NEXT);
> + if (rc) {
> + fprintf(stderr,
> + "Failed reading next capability ID at
> 0x%"PRIx64"\n",
> + offset + PCI_CAP_LIST_NEXT);
> + return;
> + }
> +
> + offset = (pciaddr_t) next_cap;
> + continue;
> + }
> +
> + /*
> + * PCIe Capability Structure exists!
> + */
Use tabs instead spaces...I think these worth fixing while strings
longer than 80 if fine as talked. Just did you miss refresh since I see
still patches has quite a bit checkpatch issues ? Like this one:-
ERROR: code indent should use tabs where possible
#259: FILE: lib/sysfs_hba.c:105:
+ /*$
ERROR: code indent should use tabs where possible
#260: FILE: lib/sysfs_hba.c:106:
+ * PCIe Capability Structure exists!$
ERROR: code indent should use tabs where possible
#261: FILE: lib/sysfs_hba.c:107:
+ */$
ERROR: code indent should use tabs where possible
#264: FILE: lib/sysfs_hba.c:110:
+ * The first PCIe extended capability is located at$
ERROR: code indent should use tabs where possible
#265: FILE: lib/sysfs_hba.c:111:
+ * offset 0x100 in the device configuration space.$
ERROR: code indent should use tabs where possible
#266: FILE: lib/sysfs_hba.c:112:
+ */$
WARNING: unchecked sscanf return value
#383: FILE: lib/sysfs_hba.c:229:
+ sscanf(pcidev, "%x:%x:%x.%x", &match.domain, &match.bus,
&match.dev,
+ &match.func);
total: 6 errors, 8 warnings, 530 lines checked
Following more patches with:
WARNING: quoted string split across lines
#276: FILE: fcoeadm_display.c:223:
+ printf(" LUN ID Device Name Capacity "
+ "Block Size Description\n");
WARNING: quoted string split across lines
#278: FILE: fcoeadm_display.c:225:
+ printf(" ------ ----------- ---------- ---------- "
+ "----------------------------\n");
WARNING: void function return statements are not generally useful
#882: FILE: fcoeadm_display.c:430:
+ return;
+}
Along fixing these, coredump also needs to be fixed. The fcoeadm -i
segfaults on two interfaces though no fault on single interface.
Here is the back trace with fault in get_ctlr_num() at
lib/sysfs_hba.c:441.
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff789b3ea in strlen () from /lib64/libc.so.6
Missing separate debuginfos, use: debuginfo-install
glibc-2.18-14.fc20.x86_64 libpciaccess-0.13.3-0.1.fc20.x86_64
(gdb) bt
#0 0x00007ffff789b3ea in strlen () from /lib64/libc.so.6
#1 0x0000000000405ce0 in get_pci_dev_from_netdev
(netdev=netdev@entry=0x60b123 "lo") at lib/sysfs_hba.c:441
#2 0x0000000000402746 in display_one_adapter_info (ifname=0x60b123
"lo") at fcoeadm_display.c:551
#3 0x000000000040295d in search_fc_adapter (dp=<optimized out>,
arg=<optimized out>) at fcoeadm_display.c:587
#4 0x0000000000404fcc in sa_dir_read (dir_name=dir_name@entry=0x40741b
"/sys/class/net/", func=func@entry=0x402950 <search_fc_adapter>,
arg=arg@entry=0x0) at lib/sa_sys.c:181
#5 0x0000000000403b91 in display_adapter_info (ifname=ifname@entry=0x0)
at fcoeadm_display.c:604
#6 0x00000000004020d0 in main (argc=2, argv=0x7fffffffe3a8) at
fcoeadm.c:325
> +
> + /*
> + * The first PCIe extended capability is located at
> + * offset 0x100 in the device configuration space.
> + */
> + offset = 0x100;
> + do {
> + rc = pci_device_cfg_read_u32(dev, &pcie_cap_header,
> + offset);
> + if (rc) {
> + fprintf(stderr,
> + "Failed reading PCIe config header\n");
> + return;
> + }
> +
> + /* Get the PCIe Extended Capability ID */
> + pcie_cap_id = pcie_cap_header & 0xffff;
> +
> + if (pcie_cap_id != PCI_EXT_CAP_ID_DSN) {
> + /* Get the offset of the next capability */
> + offset = (pciaddr_t) pcie_cap_header >> 20;
> + continue;
> + }
> +
> + /*
> + * Found the serial number register!
> + */
> +
> + (void) pci_device_cfg_read_u32(dev, &dword_low,
> + offset + 4);
> + (void) pci_device_cfg_read_u32(dev, &dword_high,
> + offset + 8);
> + snprintf(info->serial_number,
> + sizeof(info->serial_number),
> + "%02X%02X%02X%02X%02X%02X\n",
> + dword_high >> 24, (dword_high >> 16) & 0xff,
> + (dword_high >> 8) & 0xff,
> + (dword_low >> 16) & 0xff,
> + (dword_low >> 8) & 0xff, dword_low & 0xff);
> + break;
> + } while (offset);
> +
> + break;
> + }
> +}
> +
> +static void get_pci_device_info(struct pci_device *dev, struct hba_info
> *info)
> +{
> + char *unknown = "unknown";
> + const char *vname;
> + const char *dname;
> + uint8_t revision;
> +
> + vname = pci_device_get_vendor_name(dev);
> + if (!vname)
> + vname = unknown;
> +
> + strncpy(info->manufacturer, vname, sizeof(info->manufacturer));
> +
> + dname = pci_device_get_device_name(dev);
> + if (!dname)
> + dname = unknown;
> +
> + strncpy(info->model_description, dname,
> + sizeof(info->model_description));
> +
> + pci_device_cfg_read_u8(dev, &revision, PCI_REVISION_ID);
> + snprintf(info->hardware_version, sizeof(info->hardware_version),
> + "%02x", revision);
> +
> + info->nports = 1;
> +
> + get_device_serial_number(dev, info);
> +}
> +
> +static void get_module_info(const char *pcidev, struct hba_info *info)
> +{
> + char buf[1024];
> + char *path;
> + int err;
> +
> + strncpy(info->driver_name, "Unknown", sizeof(info->driver_name));
> + strncpy(info->driver_version, "Unknown", sizeof(info->driver_version));
> +
> + err = asprintf(&path, "/sys/bus/pci/devices/%s/driver/module", pcidev);
> + if (err == -1)
> + return;
> +
> + sa_sys_read_line(path, "version",
> + info->driver_version, sizeof(info->driver_version));
> +
> + err = readlink(path, buf, sizeof(buf) - 1);
> + free(path);
> + if (err == -1)
> + return;
> +
> + buf[err] = '\0';
> +
> + if (strstr(buf, "module"))
> + strncpy(info->driver_name,
> + strstr(buf, "module") + strlen("module") + 1,
> + sizeof(info->driver_name));
> +
> +}
> +
> +struct hba_info *get_hbainfo_by_pcidev(const char *pcidev)
> +{
> + struct pci_device_iterator *iterator;
> + struct pci_slot_match match;
> + struct pci_device *dev;
> + struct hba_info *info;
> + int rc;
> +
> + rc = pci_system_init();
> + if (rc)
> + return NULL;
> +
> + info = calloc(1, sizeof(struct hba_info));
> + if (!info)
> + return NULL;
> +
> + sscanf(pcidev, "%x:%x:%x.%x", &match.domain, &match.bus, &match.dev,
> + &match.func);
> +
> + iterator = pci_slot_match_iterator_create(&match);
> + if (!iterator) {
> + free(info);
> + return NULL;
> + }
> +
> + for (;;) {
> + dev = pci_device_next(iterator);
> + if (!dev)
> + break;
> + get_pci_device_info(dev, info);
> + get_module_info(pcidev, info);
> + }
> +
> + free(iterator);
> + pci_system_cleanup();
> +
> + return info;
> +}
> +
> +struct port_attributes *get_port_attribs(const char *host)
> +{
> + struct port_attributes *pa;
> + char *path;
> + int err;
> +
> + err = asprintf(&path, "%s/%s", SYSFS_HOST_DIR, host);
> + if (err == -1)
> + return NULL;
> +
> + pa = calloc(1, sizeof(*pa));
> + if (!pa)
> + goto free_path;
> +
> + strncpy(pa->device_name, host, sizeof(pa->device_name));
> +
> + sa_sys_read_line(path, "symbolic_name", pa->symbolic_name,
> + sizeof(pa->symbolic_name));
> + sa_sys_read_line(path, "node_name", pa->node_name,
> + sizeof(pa->node_name));
> + sa_sys_read_line(path, "port_name", pa->port_name,
> + sizeof(pa->port_name));
> + sa_sys_read_line(path, "fabric_name", pa->fabric_name,
> + sizeof(pa->fabric_name));
> + sa_sys_read_line(path, "speed", pa->speed, sizeof(pa->speed));
> + sa_sys_read_line(path, "supported_speeds", pa->supported_speeds,
> + sizeof(pa->supported_speeds));
> + sa_sys_read_line(path, "maxframe_size", pa->maxframe_size,
> + sizeof(pa->maxframe_size));
> + sa_sys_read_line(path, "port_id", pa->port_id, sizeof(pa->port_id));
> + sa_sys_read_line(path, "port_state", pa->port_state,
> + sizeof(pa->port_state));
> +
> +free_path:
> + free(path);
> +
> + return pa;
> +}
> +
> +char *get_pci_dev_from_netdev(const char *netdev)
> +{
> + char buf[1024];
> + char *pcidev;
> + char *path;
> + char *cp;
> + int func;
> + int dom;
> + int bus;
> + int dev;
> + int ret;
> +
> + ret = asprintf(&path, "%s/%s/device", SYSFS_NET_DIR, netdev);
> + if (ret == -1)
> + return NULL;
> +
> + ret = readlink(path, buf, sizeof(buf) - 1);
> + free(path);
> + if (ret == -1) {
> + char realdev[256];
> + char *subif;
> + size_t len;
> +
> + subif = strchr(netdev, '.');
> + len = strlen(netdev) - strlen(subif);
> + strncpy(realdev, netdev, len);
> + if (realdev[len] != '\0')
> + realdev[len] = '\0';
> +
> + ret = asprintf(&path, "%s/%s/lower_%s", SYSFS_NET_DIR,
> + netdev, realdev);
> + if (ret == -1)
> + return NULL;
> +
> + ret = readlink(path, buf, sizeof(buf) - 1);
> + free(path);
> +
> + if (ret == -1)
> + return NULL;
> + }
> +
> + do {
> + cp = strrchr(buf, '/');
> + if (!cp)
> + break;
> +
> + ret = sscanf(cp + 1, "%x:%x:%x.%x", &dom, &bus, &dev, &func);
> + if (ret == 4)
> + break;
> +
> + *cp = '\0';
> + } while (cp && cp > buf);
> +
> + ret = asprintf(&pcidev, "%04x:%02x:%02x.%x\n", dom, bus, dev, func);
> + if (ret == -1)
> + return NULL;
> +
> + return pcidev;
> +}
> +
> +char *get_host_from_netdev(const char *netdev)
> +{
> + struct dirent *dp;
> + char *host = NULL;
> + char *path = NULL;
> + DIR *dir;
> + int ret;
> +
> + ret = asprintf(&path, "%s/%s/ctlr_0/", SYSFS_NET_DIR, netdev);
> + if (ret == -1)
> + return NULL;
> +
> + dir = opendir(path);
> + free(path);
> + path = NULL;
> +
> + if (!dir)
> + return NULL;
> +
> + for (dp = readdir(dir); dp != NULL; dp = readdir(dir)) {
> + if (dp->d_name[0] == '.' && dp->d_name[1] == '\0')
> + continue;
> + if (dp->d_name[1] == '.' && dp->d_name[2] == '\0')
> + continue;
> +
> + host = strstr(dp->d_name, "host");
> + if (host) {
> + struct stat sb;
> +
> + ret = asprintf(&path, "%s/%s/ctlr_0/%s/fc_host/%s",
> + SYSFS_NET_DIR, netdev, host, host);
> + if (ret == -1)
> + goto out_closedir;
> +
> + ret = stat(path, &sb);
> + free(path);
> + path = NULL;
> +
> + if (ret == -1)
> + host = NULL;
> + break;
> +
> + }
> + }
> +
> +out_closedir:
> + closedir(dir);
> +
> + return host ? strdup(host) : NULL;
> +}
> +
> +int get_number_of_adapters(void)
> +{
> + struct dirent *dp;
> + int num = 0;
> + DIR *dir;
> +
> + dir = opendir(SYSFS_HOST_DIR);
> + if (!dir)
> + return errno;
> +
> + for (dp = readdir(dir); dp != NULL; dp = readdir(dir)) {
> + if (dp->d_name[0] == '.' && dp->d_name[1] == '\0')
> + continue;
> + if (dp->d_name[1] == '.' && dp->d_name[2] == '\0')
> + continue;
> +
> + if (strstr(dp->d_name, "host"))
> + num++;
> +
> + }
> +
> + closedir(dir);
> +
> + return num;
> +}
_______________________________________________
fcoe-devel mailing list
[email protected]
http://lists.open-fcoe.org/mailman/listinfo/fcoe-devel