All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] Add fc_id, which gives ID_PORT_NAME and ID_LUN on appropriate devices.
@ 2009-07-21 19:18 Peter Jones
  2009-07-21 19:23 ` Peter Jones
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Peter Jones @ 2009-07-21 19:18 UTC (permalink / raw)
  To: linux-hotplug

This makes it easier for consumers to use the individual pieces of
information instead of having to parse path_id's output.
---
 extras/Makefile.am       |    1 +
 extras/fc_id/.gitignore  |    1 +
 extras/fc_id/Makefile.am |   13 +++
 extras/fc_id/fc_id.c     |  271 ++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 286 insertions(+), 0 deletions(-)
 create mode 100644 extras/fc_id/.gitignore
 create mode 100644 extras/fc_id/Makefile.am
 create mode 100644 extras/fc_id/fc_id.c

diff --git a/extras/Makefile.am b/extras/Makefile.am
index b7c9fe8..5377a8e 100644
--- a/extras/Makefile.am
+++ b/extras/Makefile.am
@@ -5,6 +5,7 @@ SUBDIRS = \
 	cdrom_id \
 	edd_id \
 	path_id \
+	fc_id \
 	firmware \
 	collect \
 	floppy \
diff --git a/extras/fc_id/.gitignore b/extras/fc_id/.gitignore
new file mode 100644
index 0000000..1d7d107
--- /dev/null
+++ b/extras/fc_id/.gitignore
@@ -0,0 +1 @@
+fc_id
diff --git a/extras/fc_id/Makefile.am b/extras/fc_id/Makefile.am
new file mode 100644
index 0000000..ae90d3c
--- /dev/null
+++ b/extras/fc_id/Makefile.am
@@ -0,0 +1,13 @@
+include $(top_srcdir)/Makefile.am.inc
+
+libexec_PROGRAMS = \
+	fc_id
+
+path_id_SOURCES = \
+	fc_id.c \
+	../../libudev/libudev.h \
+	../../libudev/libudev.c \
+	../../libudev/libudev-device.c \
+	../../libudev/libudev-enumerate.c \
+	../../libudev/libudev-list.c \
+	../../libudev/libudev-util.c
diff --git a/extras/fc_id/fc_id.c b/extras/fc_id/fc_id.c
new file mode 100644
index 0000000..d8cb597
--- /dev/null
+++ b/extras/fc_id/fc_id.c
@@ -0,0 +1,271 @@
+/*
+ * report Fibre Channel Path Name and Lun
+ *
+ * Copyright (C) 2009 Kay Sievers <kay.sievers@vrfy.org>
+ * Copyright 2009 Red Hat, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <string.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <dirent.h>
+#include <getopt.h>
+
+#include "libudev.h"
+#include "libudev-private.h"
+
+int debug;
+
+static void log_fn(struct udev *udev, int priority,
+		   const char *file, int line, const char *fn,
+		   const char *format, va_list args)
+{
+	if (debug) {
+		fprintf(stderr, "%s: ", fn != NULL ? fn : file);
+		vfprintf(stderr, format, args);
+	} else {
+		vsyslog(priority, format, args);
+	}
+}
+
+static struct udev_device *skip_subsystem(struct udev_device *dev, const char *subsys)
+{
+	struct udev_device *parent = dev;
+
+	while (parent != NULL) {
+		const char *subsystem;
+
+		subsystem = udev_device_get_subsystem(parent);
+		if (subsystem = NULL || strcmp(subsystem, subsys) != 0)
+			break;
+		dev = parent;
+		parent = udev_device_get_parent(parent);
+	}
+	return dev;
+}
+
+static struct udev_device *handle_scsi_fibre_channel(struct udev_device *parent)
+{
+	struct udev *udev  = udev_device_get_udev(parent);
+	struct udev_device *targetdev;
+	struct udev_device *fcdev = NULL;
+	const char *port;
+	unsigned int lun;
+
+	targetdev = udev_device_get_parent_with_subsystem_devtype(parent, "scsi", "scsi_target");
+	if (targetdev = NULL)
+		return NULL;
+
+	fcdev = udev_device_new_from_subsystem_sysname(udev, "fc_transport", udev_device_get_sysname(targetdev));
+	if (fcdev = NULL)
+		return NULL;
+	port = udev_device_get_sysattr_value(fcdev, "port_name");
+	if (port = NULL) {
+		parent = NULL;
+		goto out;
+	}
+	lun = strtoul(udev_device_get_sysnum(parent), NULL, 10);
+
+	printf("ID_PORT_NAME=%s\n", port);
+	printf("ID_LUN=%08x\n", lun);
+out:
+	udev_device_unref(fcdev);
+	return parent;
+}
+
+static struct udev_device *handle_scsi_sas(struct udev_device *parent)
+{
+	return NULL;
+}
+
+static struct udev_device *handle_scsi_iscsi(struct udev_device *parent)
+{
+	return NULL;
+}
+
+static struct udev_device *handle_scsi(struct udev_device *parent)
+{
+	const char *devtype;
+	const char *name;
+	const char *id;
+
+	devtype = udev_device_get_devtype(parent);
+	if (devtype = NULL || strcmp(devtype, "scsi_device") != 0)
+		return parent;
+
+	/* firewire */
+	id = udev_device_get_sysattr_value(parent, "ieee1394_id");
+	if (id != NULL) {
+		parent = skip_subsystem(parent, "scsi");
+		goto out;
+	}
+
+	/* lousy scsi sysfs does not have a "subsystem" for the transport */
+	name = udev_device_get_syspath(parent);
+
+	if (strstr(name, "/rport-") != NULL) {
+		parent = handle_scsi_fibre_channel(parent);
+		goto out;
+	}
+
+	if (strstr(name, "/end_device-") != NULL) {
+		parent = handle_scsi_sas(parent);
+		goto out;
+	}
+
+	if (strstr(name, "/session") != NULL) {
+		parent = handle_scsi_iscsi(parent);
+		goto out;
+	}
+
+	parent = skip_subsystem(parent, "scsi");
+out:
+	return parent;
+}
+
+static struct udev_device *handle_cciss(struct udev_device *parent)
+{
+	return NULL;
+}
+
+static struct udev_device *handle_ccw(struct udev_device *parent, struct udev_device *dev)
+{
+	struct udev_device *scsi_dev;
+
+	scsi_dev = udev_device_get_parent_with_subsystem_devtype(dev, "scsi", "scsi_device");
+	if (scsi_dev != NULL) {
+		const char *wwpn;
+		const char *lun;
+		const char *hba_id;
+
+		hba_id = udev_device_get_sysattr_value(scsi_dev, "hba_id");
+		if (hba_id != NULL)
+			printf("ID_HDA=%s\n", hba_id);
+		wwpn = udev_device_get_sysattr_value(scsi_dev, "wwpn");
+		if (wwpn != NULL)
+			printf("ID_PORT_NAME=%s\n", wwpn);
+		lun = udev_device_get_sysattr_value(scsi_dev, "fcp_lun");
+		if (lun != NULL)
+			printf("ID_LUN=%s\n", lun);
+	}
+
+	parent = skip_subsystem(parent, "ccw");
+	return parent;
+}
+
+int main(int argc, char **argv)
+{
+	static const struct option options[] = {
+		{ "debug", no_argument, NULL, 'd' },
+		{ "help", no_argument, NULL, 'h' },
+		{}
+	};
+	struct udev *udev;
+	struct udev_device *dev;
+	struct udev_device *parent;
+	char syspath[UTIL_PATH_SIZE];
+	const char *devpath;
+	int rc = 1;
+
+	udev = udev_new();
+	if (udev = NULL)
+		goto exit;
+
+	udev_log_init("fc_id");
+	udev_set_log_fn(udev, log_fn);
+
+	while (1) {
+		int option;
+
+		option = getopt_long(argc, argv, "dh", options, NULL);
+		if (option = -1)
+			break;
+
+		switch (option) {
+		case 'd':
+			debug = 1;
+			if (udev_get_log_priority(udev) < LOG_INFO)
+				udev_set_log_priority(udev, LOG_INFO);
+			break;
+		case 'h':
+			printf("Usage: fc_id [--debug] [--help] <devpath>\n"
+			       "  --debug     print debug information\n"
+			       "  --help      print this help text\n\n");
+		default:
+			rc = 1;
+			goto exit;
+		}
+	}
+
+	devpath = argv[optind];
+	if (devpath = NULL) {
+		fprintf(stderr, "No device specified\n");
+		rc = 2;
+		goto exit;
+	}
+
+	util_strscpyl(syspath, sizeof(syspath), udev_get_sys_path(udev), devpath, NULL);
+	dev = udev_device_new_from_syspath(udev, syspath);
+	if (dev = NULL) {
+		fprintf(stderr, "unable to access '%s'\n", devpath);
+		rc = 3;
+		goto exit;
+	}
+
+	/* S390 ccw bus */
+	parent = udev_device_get_parent_with_subsystem_devtype(dev, "ccw", NULL);
+	if (parent != NULL) {
+		handle_ccw(parent, dev);
+		goto out;
+	}
+
+	/* walk up the chain of devices and compose path */
+	parent = dev;
+	while (parent != NULL) {
+		const char *subsys;
+
+		subsys = udev_device_get_subsystem(parent);
+
+		if (subsys = NULL) {
+			;
+		} else if (strcmp(subsys, "scsi") = 0) {
+			parent = handle_scsi(parent);
+		} else if (strcmp(subsys, "cciss") = 0) {
+			handle_cciss(parent);
+		} else if (strcmp(subsys, "serio") = 0) {
+			parent = skip_subsystem(parent, "serio");
+		} else if (strcmp(subsys, "pci") = 0) {
+			parent = skip_subsystem(parent, "pci");
+		} else if (strcmp(subsys, "platform") = 0) {
+			parent = skip_subsystem(parent, "platform");
+		} else if (strcmp(subsys, "xen") = 0) {
+			parent = skip_subsystem(parent, "xen");
+		}
+
+		parent = udev_device_get_parent(parent);
+	}
+out:
+	udev_device_unref(dev);
+exit:
+	udev_unref(udev);
+	udev_log_close();
+	return rc;
+}
-- 
1.6.2.2


^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2009-07-22  2:47 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-07-21 19:18 [PATCH] Add fc_id, which gives ID_PORT_NAME and ID_LUN on appropriate devices Peter Jones
2009-07-21 19:23 ` Peter Jones
2009-07-21 20:29 ` [PATCH] Add fc_id, which gives ID_PORT_NAME and ID_LUN on David Zeuthen
2009-07-21 21:07 ` [PATCH] Add fc_id, which gives ID_PORT_NAME and ID_LUN on appropriate Peter Jones
2009-07-21 22:04 ` [PATCH] Add fc_id, which gives ID_PORT_NAME and ID_LUN on Kay Sievers
2009-07-22  2:47 ` [PATCH] Add fc_id, which gives ID_PORT_NAME and ID_LUN on appropriate devices Andrey Borzenkov

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.