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

openSUSE Build Service is sponsored by