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

Reply via email to