File 0011-fcoeadm-Use-internal-sysfs-lib-to-display-target-and.patch of Package fcoe-utils
From 5943c59ae58a4b4c078c55453a8b3cef8b30d6a2 Mon Sep 17 00:00:00 2001
Message-Id: <5943c59ae58a4b4c078c55453a8b3cef8b30d6a2.1439372158.git.jthumshirn@suse.de>
In-Reply-To: <cover.1439372158.git.jthumshirn@suse.de>
References: <cover.1439372158.git.jthumshirn@suse.de>
From: Johannes Thumshirn <jthumshirn@suse.de>
Date: Mon, 3 Aug 2015 16:08:08 +0200
Subject: [PATCH 3/9] fcoeadm: Use internal sysfs lib to display target and LUN
info
Use internal sysfs lib to display target and LUN info using fcoeadm -t
or fcoeadm -l.
Signed-off-by: Johannes Thumshirn <jthumshirn@suse.de>
---
fcoeadm_display.c | 1114 +++++++++++++++++----------------------------------
fcoeadm_display.h | 4 +-
include/sysfs_hba.h | 6 +
lib/sysfs_hba.c | 73 +++-
4 files changed, 450 insertions(+), 747 deletions(-)
diff --git a/fcoeadm_display.c b/fcoeadm_display.c
index c42cba6..80b2eb9 100644
--- a/fcoeadm_display.c
+++ b/fcoeadm_display.c
@@ -17,6 +17,8 @@
* Maintained at www.Open-FCoE.org
*/
+#define _GNU_SOURCE
+
#include <sys/param.h>
#include <sys/ioctl.h>
#include <linux/types.h>
@@ -25,6 +27,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
+#include <stdbool.h>
#include <time.h>
#include <malloc.h>
#include <pthread.h>
@@ -34,6 +37,7 @@
#include <net/if.h>
#include <unistd.h>
#include <inttypes.h>
+#include <dirent.h>
#include "net_types.h"
#include "fc_types.h"
@@ -90,6 +94,14 @@ struct hba_name_table_list {
struct hba_name_table hba_table[1];
};
+/*
+ * Options for displaying target/LUN info.
+ */
+struct target_info_arguments {
+ char *ifname;
+ enum disp_style style;
+};
+
struct sa_nameval port_states[] = {
{ "Not Present", HBA_PORTSTATE_UNKNOWN },
{ "Online", HBA_PORTSTATE_ONLINE },
@@ -104,6 +116,15 @@ struct sa_nameval port_states[] = {
{ NULL, 0 }
};
+#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 */
+
+
/*
* table of /sys port speed strings to HBA-API values.
*/
@@ -122,37 +143,14 @@ struct sa_nameval port_speeds[] = {
{ NULL, 0 }
};
-static void
-sa_dump_wwn(void *Data, int Length, int Break)
-{
- unsigned char *pc = (unsigned char *)Data;
- int i;
-
- for (i = 1; i <= Length; i++) {
- printf("%02X", (int)*pc++);
- if ((Break != 0) && (!(i % Break)))
- printf(" ");
- }
-}
-
-static int is_fcp_target(HBA_PORTATTRIBUTES *rp_info)
+static int is_fcp_target(struct port_attributes *rp_info)
{
- char buf[MAX_STR_LEN];
-
- if (sa_sys_read_line(rp_info->OSDeviceName, "roles", buf, sizeof(buf)))
- return -EINVAL;
-
- if (!strncmp(buf, FCP_TARG_STR, strlen(FCP_TARG_STR)))
+ if (!strncmp(rp_info->roles, FCP_TARG_STR, strlen(FCP_TARG_STR)))
return 0;
return -EINVAL;
}
-static void show_wwn(unsigned char *pWwn)
-{
- sa_dump_wwn(pWwn, 8, 0);
-}
-
static void show_hba_info(struct hba_info *hba_info)
{
printf(" Description: %s\n", hba_info->model_description);
@@ -191,7 +189,7 @@ static void show_port_info(struct port_attributes *lp_info)
printf(" MaxFrameSize: %s\n",
lp_info->maxframe_size);
- printf(" FC-ID (Port ID): 0x%s\n",
+ printf(" FC-ID (Port ID): %s\n",
lp_info->port_id);
printf(" State: %s\n",
@@ -200,403 +198,68 @@ static void show_port_info(struct port_attributes *lp_info)
}
static void show_target_info(const char *symbolic_name,
- HBA_PORTATTRIBUTES *rp_info)
+ struct port_attributes *rp_info)
{
- char buf[256];
- int tgt_id;
- int rc;
char *ifname;
ifname = get_ifname_from_symbolic_name(symbolic_name);
- rc = sa_sys_read_line(rp_info->OSDeviceName, "roles", buf, sizeof(buf));
- if (rc)
- strncpy(buf, "Unknown", sizeof(buf));
printf(" Interface: %s\n", ifname);
- printf(" Roles: %s\n", buf);
-
- printf(" Node Name: 0x");
- show_wwn(rp_info->NodeWWN.wwn);
- printf("\n");
-
- printf(" Port Name: 0x");
- show_wwn(rp_info->PortWWN.wwn);
- printf("\n");
-
- rc = sa_sys_read_int(rp_info->OSDeviceName, "scsi_target_id", &tgt_id);
- printf(" Target ID: ");
- if (rc)
- printf("Unknown\n");
- else if (tgt_id != -1)
- printf("%d\n", tgt_id);
- else
- printf("Unset\n");
-
- printf(" MaxFrameSize: %d\n", rp_info->PortMaxFrameSize);
-
- printf(" OS Device Name: %s\n",
- strrchr(rp_info->OSDeviceName, '/') + 1);
-
- printf(" FC-ID (Port ID): 0x%06X\n", rp_info->PortFcId);
-
- sa_enum_decode(buf, sizeof(buf), port_states, rp_info->PortState);
- printf(" State: %s\n", buf);
+ printf(" Roles: %s\n", rp_info->roles);
+ printf(" Node Name: %s\n", rp_info->node_name);
+ printf(" Port Name: %s\n", rp_info->port_name);
+ printf(" Target ID: %s\n", rp_info->scsi_target_id);
+ printf(" MaxFrameSize: %s\n", rp_info->maxframe_size);
+ printf(" OS Device Name: %s\n", rp_info->device_name);
+ printf(" FC-ID (Port ID): %s\n", rp_info->port_id);
+ printf(" State: %s\n", rp_info->port_state);
printf("\n");
}
static void
-show_sense_data(char *dev, char *sense, int slen)
-{
- printf("%s", dev);
- if (slen >= 3)
- printf(" Sense Key=0x%02x", sense[2]);
- if (slen >= 13)
- printf(" ASC=0x%02x", sense[12]);
- if (slen >= 14)
- printf(" ASCQ=0x%02x\n", sense[13]);
- printf("\n");
-}
-
-#ifdef TEST_HBAAPI_V1
-static HBA_STATUS
-get_inquiry_data_v1(HBA_HANDLE hba_handle,
- HBA_FCPSCSIENTRY *ep,
- char *inqbuf, size_t inqlen)
-{
- char sense[128];
- HBA_UINT32 rlen;
- HBA_UINT32 slen;
- HBA_STATUS status;
-
- memset(inqbuf, 0, inqlen);
- memset(sense, 0, sizeof(sense));
- rlen = (HBA_UINT32) inqlen;
- slen = (HBA_UINT32) sizeof(sense);
- status = HBA_SendScsiInquiry(hba_handle,
- ep->FcpId.PortWWN,
- ep->FcpId.FcpLun,
- 0,
- 0,
- inqbuf,
- rlen,
- sense,
- slen);
- if ((status != HBA_STATUS_OK) ||
- (rlen < MIN_INQ_DATA_SIZE)) {
- fprintf(stderr,
- "%s: HBA_SendScsiInquiry failed, "
- "status=0x%x, rlen=%d\n",
- __func__, status, rlen);
- show_sense_data(ep->ScsiId.OSDeviceName, sense, slen);
- return HBA_STATUS_ERROR;
- }
- return HBA_STATUS_OK;
-}
-#else
-static HBA_STATUS
-get_inquiry_data_v2(HBA_HANDLE hba_handle,
- HBA_PORTATTRIBUTES *lp_info,
- HBA_FCPSCSIENTRYV2 *ep,
- char *inqbuf, size_t inqlen)
+show_short_lun_info_header(void)
{
- char sense[128];
- HBA_UINT32 rlen;
- HBA_UINT32 slen;
- HBA_STATUS status;
- HBA_UINT8 sstat;
-
- memset(inqbuf, 0, inqlen);
- memset(sense, 0, sizeof(sense));
- rlen = (HBA_UINT32) inqlen;
- slen = (HBA_UINT32) sizeof(sense);
- sstat = SCSI_ST_GOOD;
- status = HBA_ScsiInquiryV2(hba_handle,
- lp_info->PortWWN,
- ep->FcpId.PortWWN,
- ep->FcpId.FcpLun,
- 0,
- 0,
- inqbuf,
- &rlen,
- &sstat,
- sense,
- &slen);
- if ((status != HBA_STATUS_OK) ||
- (sstat != SCSI_ST_GOOD) ||
- (rlen < MIN_INQ_DATA_SIZE)) {
- fprintf(stderr,
- "%s: HBA_ScsiInquiryV2 failed, "
- "status=0x%x, sstat=0x%x, rlen=%d\n",
- __func__, status, sstat, rlen);
- if (sstat != SCSI_ST_GOOD)
- show_sense_data(ep->ScsiId.OSDeviceName, sense, slen);
- return HBA_STATUS_ERROR;
- }
- return HBA_STATUS_OK;
+ printf(" LUN ID Device Name Capacity "
+ "Block Size Description\n");
+ printf(" ------ ----------- ---------- ---------- "
+ "----------------------------\n");
}
-#endif
-#ifdef TEST_HBAAPI_V1
-static HBA_STATUS
-get_device_capacity_v1(HBA_HANDLE hba_handle,
- HBA_FCPSCSIENTRY *ep,
- char *buf, size_t len)
-{
- char sense[128];
- HBA_UINT32 rlen;
- HBA_UINT32 slen;
- HBA_STATUS status;
- int retry_count = 10;
-
- while (retry_count--) {
- memset(buf, 0, len);
- memset(sense, 0, sizeof(sense));
- rlen = (HBA_UINT32)len;
- slen = (HBA_UINT32)sizeof(sense);
- status = HBA_SendReadCapacity(hba_handle,
- ep->FcpId.PortWWN,
- ep->FcpId.FcpLun,
- buf,
- rlen,
- sense,
- slen);
- if (status == HBA_STATUS_OK)
- return HBA_STATUS_OK;
- if (sense[2] == 0x06)
- continue;
- fprintf(stderr,
- "%s: HBA_SendReadCapacity failed, "
- "status=0x%x, slen=%d\n",
- __func__, status, slen);
- show_sense_data(ep->ScsiId.OSDeviceName, sense, slen);
- return HBA_STATUS_ERROR;
- }
- /* retry count exhausted */
- return HBA_STATUS_ERROR;
-}
-#else
-static HBA_STATUS
-get_device_capacity_v2(HBA_HANDLE hba_handle,
- HBA_PORTATTRIBUTES *lp_info,
- HBA_FCPSCSIENTRYV2 *ep,
- char *buf, size_t len)
+static void sa_dir_crawl(char *dir_name,
+ void (*func)(char *dirname, enum disp_style style),
+ enum disp_style style)
{
- char sense[128];
- HBA_UINT32 rlen;
- HBA_UINT32 slen;
- HBA_STATUS status;
- HBA_UINT8 sstat;
- int retry_count = 10;
-
- while (retry_count--) {
- memset(buf, 0, len);
- memset(sense, 0, sizeof(sense));
- rlen = (HBA_UINT32)len;
- slen = (HBA_UINT32)sizeof(sense);
- sstat = SCSI_ST_GOOD;
- status = HBA_ScsiReadCapacityV2(hba_handle,
- lp_info->PortWWN,
- ep->FcpId.PortWWN,
- ep->FcpId.FcpLun,
- buf,
- &rlen,
- &sstat,
- sense,
- &slen);
- if ((status == HBA_STATUS_OK) && (sstat == SCSI_ST_GOOD))
- return HBA_STATUS_OK;
- if (sstat == SCSI_ST_CHECK)
- continue;
- fprintf(stderr,
- "%s: HBA_ScsiReadCapacityV2 failed, "
- "status=0x%x, sstat=0x%x, slen=%d\n",
- __func__, status, sstat, slen);
- if (sstat != SCSI_ST_GOOD)
- show_sense_data(ep->ScsiId.OSDeviceName, sense, slen);
- return HBA_STATUS_ERROR;
- }
- /* retry count exhausted */
- return HBA_STATUS_ERROR;
-}
-#endif
+ DIR *dir;
+ struct dirent *dp;
+ void (*f)(char *dirname, enum disp_style style);
+ char path[1024];
-#ifdef TEST_DEV_SERIAL_NO
-static HBA_STATUS
-get_device_serial_number(HBA_HANDLE hba_handle,
- HBA_FCPSCSIENTRYV2 *ep,
- char *buf, size_t buflen)
-{
- struct scsi_inquiry_unit_sn *unit_sn;
- char rspbuf[256];
- char sense[128];
- HBA_UINT32 rlen;
- HBA_UINT32 slen;
- HBA_STATUS status;
-
- memset(rspbuf, 0, sizeof(rspbuf));
- memset(sense, 0, sizeof(sense));
- rlen = (HBA_UINT32) sizeof(rspbuf);
- slen = (HBA_UINT32) sizeof(sense);
- status = HBA_SendScsiInquiry(hba_handle,
- ep->FcpId.PortWWN,
- ep->FcpId.FcpLun,
- SCSI_INQF_EVPD,
- SCSI_INQP_UNIT_SN,
- rspbuf,
- rlen,
- sense,
- slen);
- if (status != HBA_STATUS_OK) {
- fprintf(stderr,
- "%s: inquiry page 0x80 failed, status=0x%x\n",
- __func__, status);
- show_sense_data(ep->ScsiId.OSDeviceName, sense, slen);
- return HBA_STATUS_ERROR;
- }
- unit_sn = (struct scsi_inquiry_unit_sn *)rspbuf;
- unit_sn->is_serial[unit_sn->is_page_len] = '\0';
- sa_strncpy_safe(buf, buflen, (char *)unit_sn->is_serial,
- (size_t)unit_sn->is_page_len);
- return HBA_STATUS_OK;
-}
-#endif
+ f = func;
-#ifdef TEST_REPORT_LUNS
-static void
-show_report_luns_data(char *rspbuf)
-{
- struct scsi_report_luns_resp *rp;
- int list_len;
- net64_t *lp;
- u_int64_t lun_id;
-
- rp = (struct scsi_report_luns_resp *)rspbuf;
- list_len = net32_get(&rp->rl_len);
- printf("\tTotal Number of LUNs=%lu\n", list_len/sizeof(u_int64_t));
-
- for (lp = rp->rl_lun; list_len > 0; lp++, list_len -= sizeof(*lp)) {
- lun_id = net64_get(lp);
- if (!(lun_id & ((0xfc01ULL << 48) - 1)))
- printf("\tLUN %u\n", (u_int32_t)(lun_id >> 48));
- else
- printf("\tLUN %lx\n", (u_int64_t)lun_id);
- }
-}
+ dir = opendir(dir_name);
+ if (!dir)
+ return;
-static HBA_STATUS
-get_report_luns_data_v1(HBA_HANDLE hba_handle, HBA_FCPSCSIENTRYV2 *ep)
-{
- HBA_STATUS status;
- char rspbuf[512 * sizeof(u_int64_t)]; /* max 512 luns */
- char sense[128];
- HBA_UINT32 rlen;
- HBA_UINT32 slen;
- int retry_count = 10;
-
- while (retry_count--) {
- memset(rspbuf, 0, sizeof(rspbuf));
- memset(sense, 0, sizeof(sense));
- rlen = (HBA_UINT32) sizeof(rspbuf);
- slen = (HBA_UINT32) sizeof(sense);
- status = HBA_SendReportLUNs(hba_handle,
- ep->FcpId.PortWWN,
- rspbuf,
- rlen,
- sense,
- slen);
- if (status == HBA_STATUS_OK) {
- show_report_luns_data(rspbuf);
- return HBA_STATUS_OK;
- }
- if (sense[2] == 0x06)
+ while ((dp = readdir(dir)) != NULL) {
+ if (dp->d_name[0] == '.' && (dp->d_name[1] == '\0' ||
+ (dp->d_name[1] == '.' && dp->d_name[2] == '\0')))
continue;
- fprintf(stderr,
- "%s: HBA_SendReportLUNs failed, "
- "status=0x%x, slen=%d\n",
- __func__, status, slen);
- show_sense_data(ep->ScsiId.OSDeviceName, sense, slen);
- return HBA_STATUS_ERROR;
- }
- /* retry count exhausted */
- return HBA_STATUS_ERROR;
-}
+ snprintf(path, sizeof(path), "%s/%s", dir_name, dp->d_name);
-static HBA_STATUS
-get_report_luns_data_v2(HBA_HANDLE hba_handle,
- HBA_PORTATTRIBUTES *lp_info,
- HBA_FCPSCSIENTRYV2 *ep)
-{
- HBA_STATUS status;
- char rspbuf[512 * sizeof(u_int64_t)]; /* max 512 luns */
- char sense[128];
- HBA_UINT32 rlen;
- HBA_UINT32 slen;
- HBA_UINT8 sstat;
- int retry_count = 10;
-
- while (retry_count--) {
- memset(rspbuf, 0, sizeof(rspbuf));
- memset(sense, 0, sizeof(sense));
- rlen = (HBA_UINT32) sizeof(rspbuf);
- slen = (HBA_UINT32) sizeof(sense);
- sstat = SCSI_ST_GOOD;
- status = HBA_ScsiReportLUNsV2(hba_handle,
- lp_info->PortWWN,
- ep->FcpId.PortWWN,
- rspbuf,
- &rlen,
- &sstat,
- sense,
- &slen);
- if ((status == HBA_STATUS_OK) && (sstat == SCSI_ST_GOOD)) {
- show_report_luns_data(rspbuf);
- return HBA_STATUS_OK;
- }
- if ((sstat == SCSI_ST_CHECK) && (sense[2] == 0x06))
- continue;
- fprintf(stderr,
- "%s: HBA_ScsiReportLUNsV2 failed, "
- "status=0x%x, sstat=0x%x, slen=%d\n",
- __func__, status, sstat, slen);
- if (sstat != SCSI_ST_GOOD)
- show_sense_data(ep->ScsiId.OSDeviceName, sense, slen);
- return HBA_STATUS_ERROR;
+ f(path, style);
}
- /* retry count exhausted */
- return HBA_STATUS_ERROR;
+ closedir(dir);
}
-#endif
-static void
-show_short_lun_info_header(void)
+static char *format_capstr(uint64_t size, unsigned int blksize)
{
- printf(" LUN ID Device Name Capacity "
- "Block Size Description\n");
- printf(" ------ ----------- ---------- ---------- "
- "----------------------------\n");
-}
-
-static void
-show_short_lun_info(HBA_FCP_SCSI_ENTRY *ep, char *inqbuf,
- u_int32_t blksize,
- u_int64_t lba)
-{
- struct scsi_inquiry_std *inq = (struct scsi_inquiry_std *)inqbuf;
- char vendor[10];
- char model[20];
- char capstr[32];
- char rev[16];
- u_int64_t cap;
double cap_abbr;
+ char *capstr;
+ uint64_t cap;
char *abbr;
+ int ret;
- memset(vendor, 0, sizeof(vendor));
- memset(model, 0, sizeof(model));
- memset(capstr, 0, sizeof(capstr));
- memset(rev, 0, sizeof(rev));
-
- /* Get device capacity */
- cap = (u_int64_t)blksize * lba;
+ cap = size * blksize;
cap_abbr = cap / (1024.0 * 1024.0);
abbr = "MiB";
@@ -612,323 +275,228 @@ show_short_lun_info(HBA_FCP_SCSI_ENTRY *ep, char *inqbuf,
cap_abbr /= 1024.0;
abbr = "PiB";
}
- snprintf(capstr, sizeof(capstr), "%0.2f %s", cap_abbr, abbr);
- /* Get the device description */
- sa_strncpy_safe(vendor, sizeof(vendor),
- inq->is_vendor_id, sizeof(inq->is_vendor_id));
- sa_strncpy_safe(model, sizeof(model),
- inq->is_product, sizeof(inq->is_product));
- sa_strncpy_safe(rev, sizeof(rev), inq->is_rev_level,
- sizeof(inq->is_rev_level));
+ ret = asprintf(&capstr, "%0.2f %s", cap_abbr, abbr);
+ if (ret == -1)
+ return "Unknown";
- /* Show the LUN info */
- printf("%10d %-11s %10s %7d %s %s (rev %s)\n",
- ep->ScsiId.ScsiOSLun, ep->ScsiId.OSDeviceName,
- capstr, blksize,
- vendor, model, rev);
+ return capstr;
}
-static void
-show_full_lun_info(UNUSED HBA_HANDLE hba_handle,
- HBA_PORTATTRIBUTES *lp_info,
- HBA_PORTATTRIBUTES *rp_info,
- HBA_FCP_SCSI_ENTRY *ep,
- char *inqbuf,
- u_int32_t blksize,
- u_int64_t lba)
+static void show_full_lun_info(unsigned int hba, unsigned int port,
+ unsigned int tgt, unsigned int lun)
{
- struct scsi_inquiry_std *inq = (struct scsi_inquiry_std *)inqbuf;
- char vendor[10];
- char model[20];
- char capstr[32];
- char rev[16];
- double cap_abbr;
- char *abbr;
- u_int64_t cap;
- u_int32_t tgt_id;
- u_int8_t pqual;
-#ifdef TEST_DEV_SERIAL_NO
- HBA_STATUS status;
- char serial_number[32];
-#endif
+ char vendor[256];
+ char model[256];
+ char rev[256];
+ char *osname;
+ char *capstr;
+ uint64_t lba = 0;
+ uint32_t blksize = 0;
+ char path[1024];
+ char npath[1024];
+ DIR *dir;
+ struct dirent *dp;
+ struct port_attributes *rport_attrs;
+ struct port_attributes *port_attrs;
- memset(vendor, 0, sizeof(vendor));
- memset(model, 0, sizeof(model));
- memset(capstr, 0, sizeof(capstr));
- memset(rev, 0, sizeof(rev));
+ snprintf(path, sizeof(path),
+ "/sys/class/scsi_device/%u:%u:%u:%u",
+ hba, port, tgt, lun);
- /* Get device description */
- sa_strncpy_safe(vendor, sizeof(vendor),
- inq->is_vendor_id, sizeof(inq->is_vendor_id));
- sa_strncpy_safe(model, sizeof(model),
- inq->is_product, sizeof(inq->is_product));
- sa_strncpy_safe(rev, sizeof(rev), inq->is_rev_level,
- sizeof(inq->is_rev_level));
+ rport_attrs = get_rport_attribs_by_device(path);
+ if (!rport_attrs)
+ return;
- /* Get device capacity */
- cap = (u_int64_t)blksize * lba;
+ port_attrs = get_port_attribs_by_device(path);
+ if (!port_attrs)
+ goto free_rport;
- cap_abbr = cap / (1024.0 * 1024.0);
- abbr = "MiB";
- if (cap_abbr >= 1024) {
- cap_abbr /= 1024.0;
- abbr = "GiB";
- }
- if (cap_abbr >= 1024) {
- cap_abbr /= 1024.0;
- abbr = "TiB";
- }
- if (cap_abbr >= 1024) {
- cap_abbr /= 1024.0;
- abbr = "PiB";
+ strncat(path, "/device/", sizeof(path));
+
+ sa_sys_read_line(path, "rev", rev, sizeof(rev));
+ sa_sys_read_line(path, "model", model, sizeof(model));
+ sa_sys_read_line(path, "vendor", vendor, sizeof(vendor));
+
+ strncat(path, "block", sizeof(path));
+
+ dir = opendir(path);
+ if (!dir)
+ goto free_port;
+
+ while ((dp = readdir(dir)) != NULL) {
+ if (dp->d_name[0] == '.' && (dp->d_name[1] == '\0' ||
+ (dp->d_name[1] == '.' && dp->d_name[2] == '\0')))
+ continue;
+
+
+ osname = dp->d_name;
+
+ snprintf(npath, sizeof(npath), "%s/%s/", path, osname);
+ sa_sys_read_u64(npath, "size", &lba);
+
+ snprintf(npath, sizeof(npath), "%s/%s/queue/", path, osname);
+ sa_sys_read_u32(npath, "hw_sector_size", &blksize);
}
- snprintf(capstr, sizeof(capstr), "%0.2f %s", cap_abbr, abbr);
- /* Get SCSI target ID */
- sa_sys_read_u32(rp_info->OSDeviceName,
- "scsi_target_id", &tgt_id);
+ closedir(dir);
/* Show lun info */
- printf(" LUN #%d Information:\n", ep->ScsiId.ScsiOSLun);
+ printf(" LUN #%d Information:\n", lun);
printf(" OS Device Name: %s\n",
- ep->ScsiId.OSDeviceName);
+ osname);
printf(" Description: %s %s (rev %s)\n",
vendor, model, rev);
- printf(" Ethernet Port FCID: 0x%06X\n",
- lp_info->PortFcId);
- printf(" Target FCID: 0x%06X\n",
- rp_info->PortFcId);
- if (tgt_id == 0xFFFFFFFFU)
+ printf(" Ethernet Port FCID: %s\n",
+ port_attrs->port_id);
+ printf(" Target FCID: %s\n",
+ rport_attrs->port_id);
+ if (tgt == 0xFFFFFFFFU)
printf(" Target ID: (None)\n");
else
- printf(" Target ID: %u\n", tgt_id);
- printf(" LUN ID: %d\n",
- ep->ScsiId.ScsiOSLun);
+ printf(" Target ID: %u\n", tgt);
+ printf(" LUN ID: %d\n", lun);
+ capstr = format_capstr(lba, blksize);
printf(" Capacity: %s\n", capstr);
printf(" Capacity in Blocks: %" PRIu64 "\n", lba);
printf(" Block Size: %" PRIu32 " bytes\n", blksize);
- pqual = inq->is_periph & SCSI_INQ_PQUAL_MASK;
- if (pqual == SCSI_PQUAL_ATT)
- printf(" Status: Attached\n");
- else if (pqual == SCSI_PQUAL_DET)
- printf(" Status: Detached\n");
- else if (pqual == SCSI_PQUAL_NC)
- printf(" Status: "
- "Not capable of attachment\n");
-
-#ifdef TEST_DEV_SERIAL_NO
- /* Show the serial number of the device */
- status = get_device_serial_number(hba_handle, ep,
- serial_number, sizeof(serial_number));
- if (status == HBA_STATUS_OK)
- printf(" Serial Number: %s\n", serial_number);
-#endif
+ printf(" Status: Attached\n");
printf("\n");
+
+free_rport:
+ free(rport_attrs);
+free_port:
+ free(port_attrs);
}
-/* Compare two LUN mappings for qsort */
-static int
-lun_compare(const void *arg1, const void *arg2)
+static void show_short_lun_info(unsigned int hba, unsigned int port,
+ unsigned int tgt, unsigned int lun)
{
- const HBA_FCP_SCSI_ENTRY *e1 = arg1;
- const HBA_FCP_SCSI_ENTRY *e2 = arg2;
- int diff;
+ struct dirent *dp;
+ char vendor[256];
+ char path[1024];
+ char npath[1024];
+ char model[256];
+ char rev[256];
+ DIR *dir;
+ uint32_t blksize = 0;
+ char *capstr = "Unknown";
+ char *osname = "Unknown";
+ uint64_t size;
+
+ snprintf(path, sizeof(path),
+ "/sys/class/scsi_device/%u:%u:%u:%u/device/",
+ hba, port, tgt, lun);
+
+ sa_sys_read_line(path, "rev", rev, sizeof(rev));
+ sa_sys_read_line(path, "model", model, sizeof(model));
+ sa_sys_read_line(path, "vendor", vendor, sizeof(vendor));
+
+ strncat(path, "block", sizeof(path));
+
+ dir = opendir(path);
+ if (!dir)
+ return;
- diff = e2->FcpId.FcId - e1->FcpId.FcId;
- if (diff == 0)
- diff = e1->ScsiId.ScsiOSLun - e2->ScsiId.ScsiOSLun;
+ while ((dp = readdir(dir)) != NULL) {
+ if (dp->d_name[0] == '.' && (dp->d_name[1] == '\0' ||
+ (dp->d_name[1] == '.' && dp->d_name[2] == '\0')))
+ continue;
- return diff;
-}
-static HBA_STATUS
-get_device_map(HBA_HANDLE hba_handle, HBA_PORTATTRIBUTES *lp_info,
- HBA_FCP_TARGET_MAPPING **tgtmap, u_int32_t *lun_count)
-{
- HBA_STATUS status;
- HBA_FCP_TARGET_MAPPING *map = NULL;
- HBA_FCP_SCSI_ENTRY *ep;
- u_int32_t limit;
- u_int32_t i;
+ osname = dp->d_name;
-#define LUN_COUNT_START 8 /* number of LUNs to start with */
-#define LUN_COUNT_INCR 4 /* excess to allocate */
+ snprintf(npath, sizeof(npath), "%s/%s/", path, osname);
+ sa_sys_read_u64(npath, "size", &size);
- /*
- * Get buffer large enough to retrieve all the mappings.
- * If they don't fit, increase the size of the buffer and retry.
- */
- *lun_count = 0;
- limit = LUN_COUNT_START;
- for (;;) {
- i = (limit - 1) * sizeof(*ep) + sizeof(*map);
- map = malloc(i);
- if (map == NULL) {
- fprintf(stderr, "%s: malloc failed\n", __func__);
- return HBA_STATUS_ERROR;
- }
- memset((char *)map, 0, i);
- map->NumberOfEntries = limit;
-#ifdef TEST_HBAAPI_V1
- status = HBA_GetFcpTargetMapping(hba_handle, map);
-#else
- status = HBA_GetFcpTargetMappingV2(
- hba_handle, lp_info->PortWWN, map);
-#endif
- if (map->NumberOfEntries > limit) {
- limit = map->NumberOfEntries + LUN_COUNT_INCR;
- free(map);
- continue;
- }
- if (status != HBA_STATUS_OK) {
- fprintf(stderr,
- "%s: HBA_GetFcpTargetMappingV2 failed\n",
- __func__);
- free(map);
- return HBA_STATUS_ERROR;
- }
- break;
+ snprintf(npath, sizeof(npath), "%s/%s/queue/", path, osname);
+ sa_sys_read_u32(npath, "hw_sector_size", &blksize);
}
- if (map == NULL) {
- fprintf(stderr, "%s: map == NULL\n", __func__);
- return HBA_STATUS_ERROR;
- }
+ closedir(dir);
- if (map->NumberOfEntries > limit) {
- fprintf(stderr, "%s: map->NumberOfEntries=%d too big\n",
- __func__, map->NumberOfEntries);
- return HBA_STATUS_ERROR;
- }
+ capstr = format_capstr(size, blksize);
+
+ /* Show the LUN info */
+ printf("%10d %-11s %10s %7d %s %s (rev %s)\n",
+ lun, osname,
+ capstr, blksize,
+ vendor, model, rev);
- ep = map->entry;
- limit = map->NumberOfEntries;
+ free(capstr);
+ return;
+}
- /* Sort the response by LUN number */
- qsort(ep, limit, sizeof(*ep), lun_compare);
+static void list_scsi_device(char *d_name, enum disp_style style)
+{
+ unsigned int port;
+ unsigned int hba;
+ unsigned int tgt;
+ unsigned int lun;
+ char *last;
- *lun_count = limit;
- *tgtmap = map;
- return HBA_STATUS_OK;
+ last = strrchr(d_name, '/');
+
+ if (sscanf(last, "/%u:%u:%u:%u", &hba, &port, &tgt, &lun) != 4)
+ return;
+
+
+ if (style == DISP_TARG)
+ show_short_lun_info(hba, port, tgt, lun);
+ else
+ show_full_lun_info(hba, port, tgt, lun);
}
-static void
-scan_device_map(HBA_HANDLE hba_handle,
- HBA_PORTATTRIBUTES *lp_info,
- HBA_PORTATTRIBUTES *rp_info,
- enum disp_style style)
+static void search_rport_targets(char *d_name, enum disp_style style)
{
- HBA_STATUS status;
- HBA_FCP_TARGET_MAPPING *map = NULL;
- u_int32_t limit;
- HBA_FCP_SCSI_ENTRY *ep;
- u_int32_t i;
- char *dev;
- char inqbuf[256];
- struct scsi_rcap10_resp rcap_resp;
- struct scsi_rcap16_resp rcap16_resp;
- u_int64_t lba;
- u_int32_t blksize;
- int lun_count = 0;
- int print_header = 0;
-
- status = get_device_map(hba_handle, lp_info, &map, &limit);
- if (status != HBA_STATUS_OK) {
- fprintf(stderr, "%s: get_device_map() failed\n", __func__);
+ if (!strstr(d_name, "target"))
return;
- }
- ep = map->entry;
- for (i = 0; i < limit; i++, ep++) {
- if (ep->FcpId.FcId != rp_info->PortFcId)
- continue;
+ sa_dir_crawl(d_name, list_scsi_device, style);
+}
- dev = ep->ScsiId.OSDeviceName;
- if (strstr(dev, "/dev/") == dev)
- dev += 5;
+static void list_luns_by_rport(char *rport, enum disp_style style)
+{
+ char path[1024];
+ char link[1024];
+ char *substr;
+ int len;
+ int ret;
- /* Issue standard inquiry */
-#ifdef TEST_HBAAPI_V1
- status = get_inquiry_data_v1(hba_handle, ep,
- inqbuf, sizeof(inqbuf));
-#else
- status = get_inquiry_data_v2(hba_handle, lp_info,
- ep, inqbuf, sizeof(inqbuf));
-#endif
- if (status != HBA_STATUS_OK)
- continue;
- lun_count++;
+ snprintf(path, sizeof(path), "/sys/class/fc_remote_ports/%s", rport);
- /* Issue read capacity */
-#ifdef TEST_HBAAPI_V1
- status = get_device_capacity_v1(hba_handle, ep,
- (char *)&rcap_resp,
- sizeof(rcap_resp));
-#else
- status = get_device_capacity_v2(hba_handle, lp_info,
- ep, (char *)&rcap_resp,
- sizeof(rcap_resp));
-#endif
- if (status != HBA_STATUS_OK)
- continue;
+ ret = readlink(path, link, sizeof(link));
+ if (ret== -1)
+ return;
- if (net32_get(&rcap_resp.rc_lba) == 0xFFFFFFFFUL) {
- /* Issue read capacity (16) */
-#ifdef TEST_HBAAPI_V1
- status = get_device_capacity_v1(hba_handle, ep,
- (char *)&rcap16_resp,
- sizeof(rcap16_resp));
-#else
- status = get_device_capacity_v2(hba_handle, lp_info,
- ep, (char *)&rcap16_resp,
- sizeof(rcap16_resp));
-#endif
- if (status != HBA_STATUS_OK)
- continue;
-
- blksize = net32_get(&rcap16_resp.rc_block_len);
- lba = (u_int64_t)net64_get(&rcap16_resp.rc_lba);
- } else {
- blksize = net32_get(&rcap_resp.rc_block_len);
- lba = (u_int64_t)net32_get(&rcap_resp.rc_lba);
- }
+ if (link[ret] != '\0')
+ link[ret] = '\0';
- /* Total Number of Blocks */
- lba = lba + 1;
+ substr = strstr(link, "net");
+ snprintf(path, sizeof(path), "/sys/class/%s", substr);
- switch (style) {
- case DISP_TARG:
- if (!print_header) {
- show_short_lun_info_header();
- print_header = 1;
- }
- show_short_lun_info(ep, inqbuf, blksize, lba);
- break;
- case DISP_LUN:
- show_full_lun_info(hba_handle, lp_info,
- rp_info, ep, inqbuf, blksize, lba);
- break;
- }
+ substr = strstr(path, "fc_remote_ports");
-#ifdef TEST_REPORT_LUNS
- if (i == 0) { /* only issue report luns to the first LUN */
-#ifdef TEST_HBAAPI_V1
- get_report_luns_data_v1(hba_handle, ep);
-#else
- get_report_luns_data_v2(hba_handle, lp_info, ep);
-#endif
- }
-#endif
- }
+ len = strlen(path) - strlen(substr);
+ path[len] = '\0';
+
+ sa_dir_crawl(path, search_rport_targets, style);
+
+ return;
+}
+
+static void scan_device_map(char *port, char *rport, enum disp_style style)
+{
+ if (style == DISP_TARG)
+ show_short_lun_info_header();
+
+ list_luns_by_rport(rport, style);
/* Newline at the end of the short lun report */
if (style == DISP_TARG)
printf("\n");
-
- free(map);
}
static void show_port_stats_header(const char *ifname, int interval)
@@ -1186,7 +754,7 @@ out:
return rc;
}
-static enum fcoe_status display_one_adapter_info(const char *ifname)
+static enum fcoe_status display_one_adapter_info(char *ifname)
{
struct port_attributes *port_attrs;
struct hba_info *hba_info;
@@ -1234,7 +802,7 @@ static int search_fc_adapter(struct dirent *dp, void *arg)
return 0;
}
-enum fcoe_status display_adapter_info(const char *ifname)
+enum fcoe_status display_adapter_info(char *ifname)
{
enum fcoe_status rc = SUCCESS;
int num_hbas;
@@ -1254,101 +822,161 @@ enum fcoe_status display_adapter_info(const char *ifname)
return rc;
}
-enum fcoe_status display_target_info(const char *ifname,
- enum disp_style style)
+
+static char *get_ifname_from_rport(char *rport)
{
- HBA_STATUS retval;
- HBA_PORTATTRIBUTES rport_attrs;
- struct hba_name_table_list *hba_table_list = NULL;
- int i, num_hbas = 0;
- unsigned int target_index;
+ char link[1024];
+ char ifname[32];
+ ssize_t ret;
+ char *path;
+ char *offs;
+ int err;
+ int i = 0;
+
+ err = asprintf(&path, "%s/%s", "/sys/class/fc_remote_ports", rport);
+ if (err == -1)
+ return false;
+
+ ret = readlink(path, link, sizeof(link));
+ free(path);
+ if (ret == -1)
+ return false;
+
+ if (link[ret] != '\0')
+ link[ret] = '\0';
+
+ offs = strstr(link, "/net/");
+
+ offs = offs + 5;
+
+ for (i = 0; offs[i] != '\0'; i++)
+ if (offs[i] == '/')
+ break;
+
+ strncpy(ifname, offs, i);
+ if (ifname[i] != '\0')
+ ifname[i] = '\0';
+
+ return strdup(ifname);
+}
+
+static enum fcoe_status display_one_target_info(char *ifname, char *rport,
+ enum disp_style style)
+{
+ struct port_attributes *rport_attrs;
+ struct port_attributes *port_attrs;
enum fcoe_status rc = SUCCESS;
- HBA_HANDLE hba_handle;
- HBA_PORTATTRIBUTES *port_attrs;
+ char *host;
- if (fcoeadm_loadhba())
- return EHBAAPIERR;
+ rport_attrs = get_rport_attribs(rport);
+ if (!rport_attrs)
+ return EINTERR;
- num_hbas = hba_table_list_init(&hba_table_list);
- if (!num_hbas)
- goto out;
+ /*
+ * Skip any targets that are not FCP targets
+ */
+ if (is_fcp_target(rport_attrs))
+ goto free_rport_attribs;
- if (num_hbas < 0) {
- rc = EINTERR;
- goto out;
- }
+ rc = EINTERR;
+ host = get_host_from_netdev(ifname);
+ if (!host)
+ goto free_rport_attribs;
+
+ port_attrs = get_port_attribs(host);
+ if (!port_attrs)
+ goto free_host;
+
+ show_target_info(port_attrs->symbolic_name,
+ rport_attrs);
+
+ if (strncmp(port_attrs->port_state, "Online", 6))
+ goto free_port_attribs;
/*
- * Loop through each HBA entry and for each serial number
- * not already printed print the header and each sub-port
- * on that adapter.
+ * This will print the LUN table
+ * under the target.
*/
- for (i = 0 ; i < num_hbas ; i++) {
- if (hba_table_list->hba_table[i].failed ||
- hba_table_list->hba_table[i].displayed)
- continue;
+ scan_device_map(ifname, rport, style);
- hba_handle = hba_table_list->hba_table[i].hba_handle;
- port_attrs = &hba_table_list->hba_table[i].port_attrs;
+free_port_attribs:
+ free(port_attrs);
+free_host:
+ free(host);
+free_rport_attribs:
+ free(rport_attrs);
- if (ifname && check_symbolic_name_for_interface(
- port_attrs->PortSymbolicName,
- ifname)) {
- /*
- * Overloading 'displayed' to indicate
- * that the HBA/Port should be skipped.
- */
- hba_table_list->hba_table[i].displayed = 1;
- continue;
- }
+ return rc;
+}
- for (target_index = 0;
- target_index < port_attrs->NumberofDiscoveredPorts;
- target_index++) {
-
- /* TODO: Second arg might be incorrect */
- retval = HBA_GetDiscoveredPortAttributes(
- hba_handle,
- 0, target_index,
- &rport_attrs);
-
- if (retval != HBA_STATUS_OK) {
- fprintf(stderr,
- "HBA_GetDiscoveredPortAttributes "
- "failed for target_index=%d, "
- "status=%d\n", target_index, retval);
- hba_table_list->hba_table[i].failed = 1;
- continue;
- }
-
- /*
- * Skip any targets that are not FCP targets
- */
- if (is_fcp_target(&rport_attrs))
- continue;
-
- show_target_info(
- port_attrs->PortSymbolicName,
- &rport_attrs);
-
- if (port_attrs->PortState != HBA_PORTSTATE_ONLINE)
- continue;
-
- /*
- * This will print the LUN table
- * under the target.
- */
- scan_device_map(hba_handle,
- port_attrs,
- &rport_attrs, style);
- }
+static bool rport_is_child(const char *rport, const char *ifname)
+{
+
+ char link[1024];
+ ssize_t ret;
+ char *path;
+ char *offs;
+ int err;
+
+ err = asprintf(&path, "%s/%s", "/sys/class/fc_remote_ports", rport);
+ if (err == -1)
+ return false;
+
+ ret = readlink(path, link, sizeof(link));
+ free(path);
+ if (ret == -1)
+ return false;
+
+ offs = strstr(link, ifname);
+
+ return offs ? true : false;
+}
+
+static int search_rports(struct dirent *dp, void *arg)
+{
+ struct target_info_arguments *ta;
+ bool allocated = false; /* ifname is malloc()ed? */
+ char *ifname;
+ char *rport;
+
+
+ ta = arg;
+ rport = dp->d_name;
+ ifname = ta->ifname;
+
+ if (ifname) {
+ bool child;
+
+ child = rport_is_child(rport, ifname);
+ if (!child)
+ return 0;
+ } else {
+ ifname = get_ifname_from_rport(rport);
+ if (!ifname)
+ return -ENOMEM;
+ allocated = true;
}
- hba_table_list_destroy(hba_table_list);
-out:
- HBA_FreeLibrary();
+ display_one_target_info(ifname, rport, ta->style);
+
+ if (allocated)
+ free(ifname);
+
+ return 0;
+}
+
+enum fcoe_status display_target_info(char *ifname,
+ enum disp_style style)
+{
+ struct target_info_arguments args;
+
+ args.ifname = ifname;
+ args.style = style;
+
+ sa_dir_read("/sys/class/fc_remote_ports/", search_rports, (void *) &args);
+
+ return SUCCESS;
- return rc;
}
static struct sa_table fcoe_ctlr_table;
diff --git a/fcoeadm_display.h b/fcoeadm_display.h
index 358abf3..689c6bc 100644
--- a/fcoeadm_display.h
+++ b/fcoeadm_display.h
@@ -27,9 +27,9 @@ enum disp_style {
DISP_TARG,
};
-enum fcoe_status display_adapter_info(const char *ifname);
+enum fcoe_status display_adapter_info(char *ifname);
enum fcoe_status display_fcf_info(const char *ifname);
-enum fcoe_status display_target_info(const char *ifname,
+enum fcoe_status display_target_info(char *ifname,
enum disp_style style);
enum fcoe_status display_port_stats(const char *ifname,
int stat_interval);
diff --git a/include/sysfs_hba.h b/include/sysfs_hba.h
index 1e62477..ff6dbaf 100644
--- a/include/sysfs_hba.h
+++ b/include/sysfs_hba.h
@@ -42,6 +42,9 @@ struct port_attributes {
char maxframe_size[256];
char port_id[256];
char port_state[256];
+ char scsi_target_id[256];
+ char supported_classes[256];
+ char roles[256];
};
struct hba_info {
@@ -58,6 +61,9 @@ struct hba_info {
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);
+struct port_attributes *get_port_attribs_by_device(char *path);
+struct port_attributes *get_rport_attribs(const char *rport);
+struct port_attributes *get_rport_attribs_by_device(char *path);
char *get_pci_dev_from_netdev(const char *netdev);
char *get_host_from_netdev(const char *netdev);
diff --git a/lib/sysfs_hba.c b/lib/sysfs_hba.c
index e209dc1..0da55df 100644
--- a/lib/sysfs_hba.c
+++ b/lib/sysfs_hba.c
@@ -34,8 +34,47 @@
#include "sysfs_hba.h"
#include "fcoemon_utils.h"
-#define SYSFS_HOST_DIR "/sys/class/fc_host"
-#define SYSFS_NET_DIR "/sys/class/net"
+#define SYSFS_HOST_DIR "/sys/class/fc_host"
+#define SYSFS_NET_DIR "/sys/class/net"
+#define SYSFS_RPORT_DIR "/sys/class/fc_remote_ports"
+
+struct port_attributes *get_port_attribs_by_device(char *path)
+{
+ char link[1024];
+ char *host;
+ char *rport;
+ int ret;
+
+ ret = readlink(path, link, sizeof(link));
+ if (ret == -1)
+ return NULL;
+
+ host = strstr(link, "host");
+ rport = strstr(link, "rport");
+
+ host[strlen(host) - strlen(rport) - 1] = '\0';
+
+ return get_port_attribs(host);
+}
+
+struct port_attributes *get_rport_attribs_by_device(char *path)
+{
+ char link[1024];
+ char *target;
+ char *rport;
+ int ret;
+
+ ret = readlink(path, link, sizeof(link));
+ if (ret == -1)
+ return NULL;
+
+ target = strstr(link, "target");
+ rport = strstr(link, "rport");
+
+ rport[strlen(rport) - strlen(target) - 1] = '\0';
+
+ return get_rport_attribs(rport);
+}
static void get_device_serial_number(struct pci_device *dev,
struct hba_info *info)
@@ -221,6 +260,36 @@ struct hba_info *get_hbainfo_by_pcidev(const char *pcidev)
return info;
}
+struct port_attributes *get_rport_attribs(const char *rport)
+{
+ struct port_attributes *pa;
+ char *path;
+ int err;
+
+ err = asprintf(&path,"%s/%s", SYSFS_RPORT_DIR, rport);
+ if (err == -1)
+ return NULL;
+
+ pa = calloc(1, sizeof(*pa));
+ if (!pa)
+ goto free_path;
+
+ strncpy(pa->device_name, rport, sizeof(pa->device_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, "port_id", pa->port_id, sizeof(pa->port_id));
+ sa_sys_read_line(path, "scsi_target_id", pa->scsi_target_id, sizeof(pa->scsi_target_id));
+ sa_sys_read_line(path, "maxframe_size", pa->maxframe_size, sizeof(pa->maxframe_size));
+ sa_sys_read_line(path, "port_state", pa->port_state, sizeof(pa->port_state));
+ sa_sys_read_line(path, "supported_classes", pa->supported_classes, sizeof(pa->supported_classes));
+ sa_sys_read_line(path, "roles", pa->roles, sizeof(pa->roles));
+
+free_path:
+ free(path);
+
+ return pa;
+}
+
struct port_attributes *get_port_attribs(const char *host)
{
struct port_attributes *pa;
--
2.4.6