[PATCH] Add fc_id, which gives ID_PORT_NAME and ID_LUN on appropriate devices.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This makes it easier for consumers to use the individual pieces of
information instead of having to parse path_id's output.

(this version fixes Makefile.am)
---
 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..6d4c8d1
--- /dev/null
+++ b/extras/fc_id/Makefile.am
@@ -0,0 +1,13 @@
+include $(top_srcdir)/Makefile.am.inc
+
+libexec_PROGRAMS = \
+	fc_id
+
+fc_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@xxxxxxxx>
+ * 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

--
To unsubscribe from this list: send the line "unsubscribe linux-hotplug" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Kernel]     [Linux DVB]     [Asterisk Internet PBX]     [DCCP]     [Netdev]     [X.org]     [Util Linux NG]     [Fedora Women]     [ALSA Devel]     [Linux USB]

  Powered by Linux