linux-hotplug.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Scott James Remnant <scott@ubuntu.com>
To: linux-hotplug@vger.kernel.org
Subject: Re: [PATCH] add options to udevtrigger to control scanning
Date: Thu, 31 Aug 2006 20:02:45 +0000	[thread overview]
Message-ID: <1157054565.14312.14.camel@quest.netsplit.com> (raw)
In-Reply-To: <20060831004138.GA28528@kroah.com>


[-- Attachment #1.1.1: Type: text/plain, Size: 736 bytes --]

On Thu, 2006-08-31 at 10:31 -0700, Greg KH wrote:

> > The Ubuntu guys use a patch which can filter on values to have control
> > over what is triggered and what not. If we are going that road, I like
> > their patch more than this.
> 
> Do you have a pointer to where this patch is?
> 
Attached;  I sent it to this list a while back as part of my "patches
collection" mail.

The reason we use this is that we try and have an initramfs that works
on every single machine, rather than produce a tailored one for the
machine underneath.

So we take a little more care about what we coldplug and when -- rather
than just probing for everything and hoping for the best.

Scott
-- 
Scott James Remnant
scott@ubuntu.com

[-- Attachment #1.1.2: 40-udevtrigger-filters.patch --]
[-- Type: text/x-patch, Size: 16480 bytes --]

diff -ruNp udev-093~/udevtrigger.8 udev-093/udevtrigger.8
--- udev-093~/udevtrigger.8	2006-05-29 10:18:16.000000000 +0100
+++ udev-093/udevtrigger.8	2006-06-07 19:30:30.000000000 +0100
@@ -1,37 +1,100 @@
-.\" ** You probably do not want to edit this file directly **
-.\" It was generated using the DocBook XSL Stylesheets (version 1.69.1).
-.\" Instead of manually editing it, you probably should edit the DocBook XML
-.\" source for it and then use the DocBook XSL Stylesheets to regenerate it.
-.TH "UDEVTRIGGER" "8" "March 2006" "udev" "udevtrigger"
-.\" disable hyphenation
-.nh
-.\" disable justification (adjust text to left margin only)
-.ad l
-.SH "NAME"
+.\"Generated by db2man.xsl. Don't modify this, modify the source.
+.de Sh \" Subsection
+.br
+.if t .Sp
+.ne 5
+.PP
+\fB\\$1\fR
+.PP
+..
+.de Sp \" Vertical space (when we can't use .PP)
+.if t .sp .5v
+.if n .sp
+..
+.de Ip \" List item
+.br
+.ie \\n(.$>=3 .ne \\$3
+.el .ne 3
+.IP "\\$1" \\$2
+..
+.TH "UDEVTRIGGER" 8 "March 2006" "udev" "udevtrigger"
+.SH NAME
 udevtrigger \- request kernel devices events for coldplug
 .SH "SYNOPSIS"
+.ad l
+.hy 0
 .HP 12
-\fBudevtrigger\fR [\fB\-\-verbose\fR] [\fB\-\-dry\-run\fR]
+\fBudevtrigger\fR [\fB\-\-verbose\fR] [\fB\-\-dry\-run\fR] [\fB\-\-serial\fR] [\fBFILTER\&.\&.\&.\fR]
+.ad
+.hy
+
 .SH "DESCRIPTION"
+
 .PP
-Trigger kernel device uevents to replay missing events at system coldplug.
+Trigger kernel device uevents to replay missing events at system coldplug\&.
+
 .SH "OPTIONS"
+
 .TP
 \fB\-\-verbose\fR
-print out the devices found in sysfs.
+print out the devices found in sysfs\&.
+
 .TP
 \fB\-\-dry\-run\fR
-don't actually trigger the event.
+don't actually trigger the event\&.
+
+.TP
+\fB\-\-serial\fR
+run udevsettle between events\&.
+
+.SH "FILTER OPTIONS"
+
+.PP
+All options are accumulative and may be specified multiple times
+
+.TP
+\fB\-I\fIattr\fR=\fIvalue\fR\fR
+only those devices for which the given attribute matches the value (which may include wildcards) are triggered
+
+.TP
+\fB\-X\fIattr\fR=\fIvalue\fR\fR
+only those devices for which the given attribute DOES NOT MATCH the value (which may include wildcards) are triggered
+
+.TP
+\fB\-B\fIbus\fR\fR
+devices on the given bus are triggered
+
+.TP
+\fB\-C\fIclass\fR\fR
+devices in the given class are triggered
+
+.TP
+\fB\-F\fR
+devices that have previously failed are triggered
+
+.TP
+\fB\-b\fR
+block devices are triggered
+
+.TP
+\fB\-c\fR
+class devices are triggered
+
 .SH "ENVIRONMENT"
+
 .TP
 \fBUDEV_LOG\fR
-Overrides the syslog priority specified in the config file.
+Overrides the syslog priority specified in the config file\&.
+
 .SH "AUTHOR"
+
 .PP
-Written by Kay Sievers
-<kay.sievers@vrfy.org>
-and Hannes Reinecke
-<hare@suse.de>.
+Written by Kay Sievers <kay\&.sievers@vrfy\&.org> and Hannes Reinecke <hare@suse\&.de>\&.
+
 .SH "SEE ALSO"
+
 .PP
 \fBudev\fR(7)
+
+.SH AUTHOR
+Kay Sievers.
diff -ruNp udev-093~/udevtrigger.c udev-093/udevtrigger.c
--- udev-093~/udevtrigger.c	2006-05-29 10:18:16.000000000 +0100
+++ udev-093/udevtrigger.c	2006-06-07 20:06:31.000000000 +0100
@@ -27,15 +27,19 @@
 #include <errno.h>
 #include <dirent.h>
 #include <fcntl.h>
+#include <ctype.h>
 #include <syslog.h>
 #include <sys/stat.h>
 #include <sys/types.h>
+#include <sys/wait.h>
 
 #include "udev.h"
+#include "udevd.h"
 
 static const char *udev_log_str;
 static int verbose;
 static int dry_run;
+static int serial_plug;
 
 #ifdef USE_LOG
 void log_message(int priority, const char *format, ...)
@@ -96,11 +100,89 @@ static int device_list_insert(const char
 	return 0;
 }
 
+struct filter {
+	struct list_head node;
+	char name[NAME_SIZE];
+	char value[VALUE_SIZE];
+	int include;
+};
+
+LIST_HEAD(filter_list);
+
+static int filter_list_insert(int include, const char *filter)
+{
+	struct filter *new_filter;
+	const char *ptr;
+
+	new_filter = malloc(sizeof(struct filter));
+	if (!new_filter) {
+		dbg("error malloc");
+		return -ENOMEM;
+	}
+	new_filter->include = include;
+
+	ptr = strchr(filter, '=');
+	if (ptr) {
+		if ((size_t)(ptr + 1 - filter) > sizeof(new_filter->name)) {
+			err("attribute name too long in filter %s", filter);
+			free(new_filter);
+			return 1;
+		}
+		memcpy(new_filter->name, filter, ptr - filter);
+		new_filter->name[ptr - filter] = '\0';
+
+		strlcpy(new_filter->value, ptr + 1, sizeof(new_filter->value));
+	} else {
+		strlcpy(new_filter->name, filter, sizeof(new_filter->name));
+		strlcpy(new_filter->value, "?*", sizeof(new_filter->value));
+	}
+
+	list_add_tail(&new_filter->node, &filter_list);
+	dbg("add %s filter '%s' value '%s'",
+	    new_filter->include ? "include" : "exclude",
+	    new_filter->name, new_filter->value);
+	return 0;
+}
+
 static void trigger_uevent(const char *path)
 {
+	struct filter *loop_filter;
+	const char *devpath;
 	char filename[PATH_SIZE];
 	int fd;
 
+	devpath = path;
+	if (!strncmp (devpath, sysfs_path, strlen(sysfs_path)))
+		devpath += strlen(sysfs_path);
+
+	list_for_each_entry(loop_filter, &filter_list, node) {
+		char *attr, value[256];
+		int i;
+
+		attr = sysfs_attr_get_value(devpath, loop_filter->name);
+		if (!attr) {
+			if (loop_filter->include)
+				return;
+
+			continue;
+		}
+
+		i = strlcpy(value, attr, sizeof(value));
+		while (i > 0 && isspace(value[i-1]))
+			value[--i] = '\0';
+
+		if (strcmp_pattern(loop_filter->value, value) == 0) {
+			dbg("device '%s' attr '%s' matched filter '%s' <-> '%s'",
+			    path, loop_filter->name, value, loop_filter->value);
+
+			if (!loop_filter->include)
+				return;
+		} else {
+			if (loop_filter->include)
+				return;
+		}
+	}
+
 	strlcpy(filename, path, sizeof(filename));
 	strlcat(filename, "/uevent", sizeof(filename));
 
@@ -120,6 +202,24 @@ static void trigger_uevent(const char *p
 		info("error on triggering %s: %s\n", filename, strerror(errno));
 
 	close(fd);
+
+	if (serial_plug && !dry_run) {
+		pid_t pid;
+
+		pid = fork();
+		switch(pid) {
+		case 0:
+			execl("/sbin/udevsettle", "/sbin/udevsettle", NULL);
+
+			/* we should never reach this */
+			err("exec of udevsettle failed");
+			_exit(1);
+		case -1:
+			err("fork of udevsettle failed: %s", strerror(errno));
+		default:
+			waitpid(pid, NULL, 0);
+		}
+	}
 }
 
 static void exec_lists(void)
@@ -166,6 +266,35 @@ static int is_device(const char *path)
 	return 1;
 }
 
+static void udev_scan_bus_devices(const char *devpath)
+{
+	char dirname[PATH_SIZE];
+	DIR *dir2;
+	struct dirent *dent2;
+
+	strlcpy(dirname, devpath, sizeof(dirname));
+	strlcat(dirname, "/devices", sizeof(dirname));
+
+	/* look for devices */
+	dir2 = opendir(dirname);
+	if (dir2 != NULL) {
+		for (dent2 = readdir(dir2); dent2 != NULL; dent2 = readdir(dir2)) {
+			char dirname2[PATH_SIZE];
+
+			if (dent2->d_name[0] == '.')
+				continue;
+
+			strlcpy(dirname2, dirname, sizeof(dirname2));
+			strlcat(dirname2, "/", sizeof(dirname2));
+			strlcat(dirname2, dent2->d_name, sizeof(dirname2));
+
+			if (is_device(dirname2))
+				device_list_insert(dirname2);
+		}
+		closedir(dir2);
+	}
+}
+
 static void udev_scan_bus(void)
 {
 	char base[PATH_SIZE];
@@ -179,8 +308,6 @@ static void udev_scan_bus(void)
 	if (dir != NULL) {
 		for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
 			char dirname[PATH_SIZE];
-			DIR *dir2;
-			struct dirent *dent2;
 
 			if (dent->d_name[0] == '.')
 				continue;
@@ -188,31 +315,24 @@ static void udev_scan_bus(void)
 			strlcpy(dirname, base, sizeof(dirname));
 			strlcat(dirname, "/", sizeof(dirname));
 			strlcat(dirname, dent->d_name, sizeof(dirname));
-			strlcat(dirname, "/devices", sizeof(dirname));
-
-			/* look for devices */
-			dir2 = opendir(dirname);
-			if (dir2 != NULL) {
-				for (dent2 = readdir(dir2); dent2 != NULL; dent2 = readdir(dir2)) {
-					char dirname2[PATH_SIZE];
 
-					if (dent2->d_name[0] == '.')
-						continue;
-
-					strlcpy(dirname2, dirname, sizeof(dirname2));
-					strlcat(dirname2, "/", sizeof(dirname2));
-					strlcat(dirname2, dent2->d_name, sizeof(dirname2));
-
-					if (is_device(dirname2))
-						device_list_insert(dirname2);
-				}
-				closedir(dir2);
-			}
+			udev_scan_bus_devices(dirname);
 		}
 		closedir(dir);
 	}
 }
 
+static void udev_scan_one_bus(const char *bus)
+{
+	char base[PATH_SIZE];
+
+	strlcpy(base, sysfs_path, sizeof(base));
+	strlcat(base, "/bus/", sizeof(base));
+	strlcat(base, bus, sizeof(base));
+
+	udev_scan_bus_devices(base);
+}
+
 static void udev_scan_block(void)
 {
 	char base[PATH_SIZE];
@@ -272,6 +392,32 @@ static void udev_scan_block(void)
 	}
 }
 
+static void udev_scan_class_devices(const char *devpath)
+{
+	DIR *dir2;
+	struct dirent *dent2;
+
+	dir2 = opendir(devpath);
+	if (dir2 != NULL) {
+		for (dent2 = readdir(dir2); dent2 != NULL; dent2 = readdir(dir2)) {
+			char dirname[PATH_SIZE];
+
+			if (dent2->d_name[0] == '.')
+				continue;
+
+			if (!strcmp(dent2->d_name, "device"))
+				continue;
+
+			strlcpy(dirname, devpath, sizeof(dirname));
+			strlcat(dirname, "/", sizeof(dirname));
+			strlcat(dirname, dent2->d_name, sizeof(dirname));
+			if (is_device(dirname))
+				device_list_insert(dirname);
+		}
+		closedir(dir2);
+	}
+}
+
 static void udev_scan_class(void)
 {
 	char base[PATH_SIZE];
@@ -285,8 +431,6 @@ static void udev_scan_class(void)
 	if (dir != NULL) {
 		for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
 			char dirname[PATH_SIZE];
-			DIR *dir2;
-			struct dirent *dent2;
 
 			if (dent->d_name[0] == '.')
 				continue;
@@ -294,25 +438,54 @@ static void udev_scan_class(void)
 			strlcpy(dirname, base, sizeof(dirname));
 			strlcat(dirname, "/", sizeof(dirname));
 			strlcat(dirname, dent->d_name, sizeof(dirname));
-			dir2 = opendir(dirname);
-			if (dir2 != NULL) {
-				for (dent2 = readdir(dir2); dent2 != NULL; dent2 = readdir(dir2)) {
-					char dirname2[PATH_SIZE];
 
-					if (dent2->d_name[0] == '.')
-						continue;
+			udev_scan_class_devices(dirname);
+		}
+		closedir(dir);
+	}
+}
 
-					if (!strcmp(dent2->d_name, "device"))
-						continue;
+static void udev_scan_one_class(const char *class)
+{
+	char base[PATH_SIZE];
 
-					strlcpy(dirname2, dirname, sizeof(dirname2));
-					strlcat(dirname2, "/", sizeof(dirname2));
-					strlcat(dirname2, dent2->d_name, sizeof(dirname2));
-					if (is_device(dirname2))
-						device_list_insert(dirname2);
-				}
-				closedir(dir2);
-			}
+	strlcpy(base, sysfs_path, sizeof(base));
+	strlcat(base, "/class/", sizeof(base));
+	strlcat(base, class, sizeof(base));
+
+	udev_scan_class_devices(base);
+}
+
+static void udev_scan_failed(void)
+{
+	char base[PATH_SIZE];
+	DIR *dir;
+	struct dirent *dent;
+
+	strlcpy(base, udev_root, sizeof(base));
+	strlcat(base, "/", sizeof(base));
+	strlcat(base, EVENT_FAILED_DIR, sizeof(base));
+
+	dir = opendir(base);
+	if (dir != NULL) {
+		for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
+			char linkname[PATH_SIZE];
+			char dirname[PATH_SIZE];
+
+			if (dent->d_name[0] == '.')
+				continue;
+
+			strlcpy(linkname, base, sizeof(linkname));
+			strlcat(linkname, "/", sizeof(linkname));
+			strlcat(linkname, dent->d_name, sizeof(linkname));
+
+			if (readlink(linkname, dirname, sizeof(dirname)) == 0)
+				continue;
+
+			if (is_device(dirname))
+				device_list_insert(dirname);
+			else
+				continue;
 		}
 		closedir(dir);
 	}
@@ -320,6 +493,7 @@ static void udev_scan_class(void)
 
 int main(int argc, char *argv[], char *envp[])
 {
+	int scan_default = 1;
 	int i;
 
 	logging_init("udevtrigger");
@@ -328,6 +502,8 @@ int main(int argc, char *argv[], char *e
 
 	udev_log_str = getenv("UDEV_LOG");
 
+	sysfs_init();
+
 	for (i = 1 ; i < argc; i++) {
 		char *arg = argv[i];
 
@@ -335,17 +511,40 @@ int main(int argc, char *argv[], char *e
 			verbose = 1;
 		else if (strcmp(arg, "--dry-run") == 0 || strcmp(arg, "-n") == 0)
 			dry_run = 1;
-		else {
-			fprintf(stderr, "Usage: udevtrigger [--verbose] [--dry-run]\n");
+		else if (strcmp(arg, "--serial") == 0 || strcmp(arg, "-s") == 0)
+			serial_plug = 1;
+		else if (strncmp(arg, "-I", 2) == 0)
+			filter_list_insert(1, arg + 2);
+		else if (strncmp(arg, "-X", 2) == 0)
+			filter_list_insert(0, arg + 2);
+		else if (strncmp(arg, "-B", 2) == 0) {
+			udev_scan_one_bus(arg + 2);
+			scan_default = 0;
+		} else if (strncmp(arg, "-C", 2) == 0) {
+			udev_scan_one_class(arg + 2);
+			scan_default = 0;
+		} else if (strcmp(arg, "-F") == 0) {
+			udev_scan_failed();
+			scan_default = 0;
+		} else if (strcmp(arg, "-b") == 0) {
+			udev_scan_one_class("block");
+			udev_scan_block();
+			scan_default = 0;
+		} else if (strcmp(arg, "-c") == 0) {
+			udev_scan_class();
+			scan_default = 0;
+		} else {
+			fprintf(stderr, "Usage: udevtrigger [--verbose] [--dry-run] [--serial] [FILTER...]\n");
 			goto exit;
 		}
 	}
 
-	sysfs_init();
+	if (scan_default) {
+		udev_scan_bus();
+		udev_scan_class();
+		udev_scan_block();
+	}
 
-	udev_scan_bus();
-	udev_scan_class();
-	udev_scan_block();
 	exec_lists();
 
 	sysfs_cleanup();
diff -ruNp udev-093~/udevtrigger.xml udev-093/udevtrigger.xml
--- udev-093~/udevtrigger.xml	2006-05-29 10:18:16.000000000 +0100
+++ udev-093/udevtrigger.xml	2006-06-07 19:30:17.000000000 +0100
@@ -39,6 +39,8 @@
           <command>udevtrigger</command>
           <arg><option>--verbose</option></arg>
           <arg><option>--dry-run</option></arg>
+          <arg><option>--serial</option></arg>
+          <arg><option>FILTER...</option></arg>
         </cmdsynopsis>
       </refsynopsisdiv>
 
@@ -60,6 +62,63 @@
               <para>don't actually trigger the event.</para>
             </listitem>
           </varlistentry>
+          <varlistentry>
+            <term><option>--serial</option></term>
+            <listitem>
+              <para>run udevsettle between events.</para>
+            </listitem>
+          </varlistentry>
+        </variablelist>
+      </refsect1>
+
+      <refsect1><title>FILTER OPTIONS</title>
+      <para>All options are accumulative and may be specified multiple times</para>
+        <variablelist>
+          <varlistentry>
+            <term><option>-I<replaceable>attr</replaceable>=<replaceable>value</replaceable></option></term>
+            <listitem>
+              <para>only those devices for which the given attribute matches
+	      the value (which may include wildcards) are triggered</para>
+            </listitem>
+          </varlistentry>
+          <varlistentry>
+            <term><option>-X<replaceable>attr</replaceable>=<replaceable>value</replaceable></option></term>
+            <listitem>
+              <para>only those devices for which the given attribute DOES
+	      NOT MATCH the value (which may include wildcards) are
+	      triggered</para>
+            </listitem>
+          </varlistentry>
+          <varlistentry>
+            <term><option>-B<replaceable>bus</replaceable></option></term>
+            <listitem>
+              <para>devices on the given bus are triggered</para>
+            </listitem>
+          </varlistentry>
+          <varlistentry>
+            <term><option>-C<replaceable>class</replaceable></option></term>
+            <listitem>
+              <para>devices in the given class are triggered</para>
+            </listitem>
+          </varlistentry>
+          <varlistentry>
+            <term><option>-F</option></term>
+            <listitem>
+              <para>devices that have previously failed are triggered</para>
+            </listitem>
+          </varlistentry>
+          <varlistentry>
+            <term><option>-b</option></term>
+            <listitem>
+              <para>block devices are triggered</para>
+            </listitem>
+          </varlistentry>
+          <varlistentry>
+            <term><option>-c</option></term>
+            <listitem>
+              <para>class devices are triggered</para>
+            </listitem>
+          </varlistentry>
         </variablelist>
       </refsect1>
 

[-- Attachment #1.2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 191 bytes --]

[-- Attachment #2: Type: text/plain, Size: 373 bytes --]

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642

[-- Attachment #3: Type: text/plain, Size: 226 bytes --]

_______________________________________________
Linux-hotplug-devel mailing list  http://linux-hotplug.sourceforge.net
Linux-hotplug-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-hotplug-devel

  parent reply	other threads:[~2006-08-31 20:02 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-08-31  0:41 [PATCH] add options to udevtrigger to control scanning Greg KH
2006-08-31  8:46 ` Kay Sievers
2006-08-31 17:31 ` Greg KH
2006-08-31 17:37 ` Marco d'Itri
2006-08-31 17:52 ` Greg KH
2006-08-31 20:02 ` Scott James Remnant [this message]
2006-09-02 17:46 ` Roy Marples
2006-09-03  1:34 ` Kay Sievers
2006-09-03  3:46 ` Greg KH
2006-09-03  4:03 ` Greg KH

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1157054565.14312.14.camel@quest.netsplit.com \
    --to=scott@ubuntu.com \
    --cc=linux-hotplug@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).