linux-hotplug.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* move udev-rules parsing into the daemon
@ 2005-07-31  0:42 Kay Sievers
  2005-08-02  2:42 ` Kay Sievers
                   ` (8 more replies)
  0 siblings, 9 replies; 10+ messages in thread
From: Kay Sievers @ 2005-07-31  0:42 UTC (permalink / raw)
  To: linux-hotplug

[-- Attachment #1: Type: text/plain, Size: 700 bytes --]

Here we move the parsed rules into the udev daemon, which will no longer
execute the udev binary. This saves us the rule parsing, cause the
parsed rules will be inherited from the daemon process, which will
fork() a child which imediately becomes the event process without doing
an exec(). It's basically a retry of this old patch:
  http://marc.theaimsgroup.com/?l=linux-hotplug-devel&m=109814301613236&w=2

Changes to /etc/udev/rules.d/* will automatically recognized and will cause
a reload of the rules, also the usual -HUP should work.

Would be nice if someone brave enough can give it a try, we want to put
that upstream if it works as expected. The patch applies on top of v064.

Thanks,
Kay

[-- Attachment #2: udevd-noexec-12.patch --]
[-- Type: text/plain, Size: 5399 bytes --]

diff --git a/RELEASE-NOTES b/RELEASE-NOTES
--- a/RELEASE-NOTES
+++ b/RELEASE-NOTES
@@ -1,3 +1,21 @@
+udev 065
+========
+
+
+udev 064
+========
+Mostly bugfixes and see ChangeLog.
+
+The test for the existence of an environment value should be
+switched from:
+  ENV{KEY}=="*" to ENV{KEY}=="?*"
+cause "*" will not fail anymore, if the key does not exist or
+is empty.
+
+udev 063
+========
+Bugfixes and a few tweaks described in the ChangeLog.
+
 udev 062
 ========
 Mostly a Bugfix release.
diff --git a/udevcontrol.c b/udevcontrol.c
--- a/udevcontrol.c
+++ b/udevcontrol.c
@@ -97,7 +97,9 @@ int main(int argc, char *argv[], char *e
 		usend_msg.type = UDEVD_SET_MAX_CHILDS;
 		*intval = atoi(val);
 		info("send max_childs=%i", *intval);
-	} else {
+	} else if (!strcmp(argv[1], "reload_rules"))
+		usend_msg.type = UDEVD_RELOAD_RULES;
+	else {
 		err("error parsing command\n");
 		goto exit;
 	}
diff --git a/udevd.c b/udevd.c
--- a/udevd.c
+++ b/udevd.c
@@ -45,6 +45,7 @@
 #include "udev_libc_wrapper.h"
 #include "udev.h"
 #include "udev_version.h"
+#include "udev_rules.h"
 #include "udev_utils.h"
 #include "udevd.h"
 #include "logging.h"
@@ -54,6 +55,7 @@
 #endif
 
 /* global variables*/
+struct udev_rules rules;
 static int udevd_sock;
 static int uevent_netlink_sock;
 static pid_t sid;
@@ -65,6 +67,7 @@ static volatile int sig_flag;
 static int init_phase = 1;
 static int run_exec_q;
 static int stop_exec_q;
+static int reload_config;
 
 static LIST_HEAD(msg_list);
 static LIST_HEAD(exec_list);
@@ -167,10 +170,54 @@ static void msg_queue_insert(struct ueve
 	return;
 }
 
+static void asmlinkage udev_event_sig_handler(int signum)
+{
+	if (signum == SIGALRM)
+		exit(1);
+}
+
+static int udev_event_process(struct uevent_msg *msg)
+{
+	struct sigaction act;
+	struct udevice udev;
+	struct name_entry *name_loop;
+	int i;
+	int retval;
+
+	logging_init("udevd-event");
+
+	/* set signal handlers */
+	memset(&act, 0x00, sizeof(act));
+	act.sa_handler = (void (*)(int)) udev_event_sig_handler;
+	sigemptyset (&act.sa_mask);
+	act.sa_flags = 0;
+	sigaction(SIGALRM, &act, NULL);
+
+	/* trigger timeout to prevent hanging processes */
+	alarm(UDEV_ALARM_TIMEOUT);
+
+	/* reconstruct env */
+	for (i = 0; msg->envp[i]; i++)
+		putenv(msg->envp[i]);
+
+	udev_init_device(&udev, msg->devpath, msg->subsystem, msg->action);
+	retval = udev_process_event(&rules, &udev);
+
+	/* run programs collected by RUN-key*/
+	if (!retval) {
+		list_for_each_entry(name_loop, &udev.run_list, node)
+			execute_program(name_loop->name, udev.subsystem, NULL, 0, NULL);
+	}
+
+	udev_cleanup_device(&udev);
+	logging_close();
+
+	return 0;
+}
+
 /* forks event and removes event from run queue when finished */
 static void udev_event_fork(struct uevent_msg *msg)
 {
-	char *const argv[] = { "udev", msg->subsystem, NULL };
 	pid_t pid;
 	struct sysinfo info;
 
@@ -183,9 +230,9 @@ static void udev_event_fork(struct ueven
 		close(udevd_sock);
 		logging_close();
 		setpriority(PRIO_PROCESS, 0, UDEV_PRIORITY);
-		execve(udev_bin, argv, msg->envp);
-		err("exec of child failed");
-		_exit(1);
+
+		udev_event_process(msg);
+		exit(0);
 	case -1:
 		err("fork of child failed");
 		msg_queue_delete(msg);
@@ -580,6 +627,11 @@ static struct uevent_msg *get_udevd_msg(
 		info("udevd message (UDEVD_SET_MAX_CHILDS) received, max_childs=%i", *intval);
 		max_childs = *intval;
 		break;
+	case UDEVD_RELOAD_RULES:
+		info("udevd message (RELOAD_RULES) received");
+		udev_rules_close(&rules);
+		udev_rules_init(&rules, 1);
+		break;
 	default:
 		dbg("unknown message type");
 	}
@@ -650,16 +702,17 @@ static void asmlinkage sig_handler(int s
 		case SIGALRM:
 			/* set flag, then write to pipe if needed */
 			run_msg_q = 1;
-			goto do_write;
 			break;
 		case SIGCHLD:
 			/* set flag, then write to pipe if needed */
 			sigchilds_waiting = 1;
-			goto do_write;
+			break;
+		case SIGHUP:
+		case SIGIO:
+			reload_config = 1;
 			break;
 	}
 
-do_write:
 	/* if pipe is empty, write to pipe to force select to return
 	 * immediately when it gets called
 	 */
@@ -787,6 +840,24 @@ static int init_uevent_netlink_sock(void
 	return 0;
 }
 
+static int watch_directory(const char *dir)
+{
+	int fd;
+
+	fd = open(dir, O_RDONLY);
+	if (fd < 0) {
+		err("could not open '%s' to watch it", dir);
+		return -1;
+	}
+	if (fcntl(fd, F_NOTIFY, DN_MODIFY | DN_CREATE | DN_DELETE | DN_MULTISHOT) == -1) {
+		err("could not set dnotify on '%s'", dir);
+		return -1;
+		close(fd);
+	}
+
+	return 0;
+}
+
 int main(int argc, char *argv[], char *envp[])
 {
 	int maxsockplus;
@@ -891,6 +962,11 @@ int main(int argc, char *argv[], char *e
 	sigaction(SIGTERM, &act, NULL);
 	sigaction(SIGALRM, &act, NULL);
 	sigaction(SIGCHLD, &act, NULL);
+	sigaction(SIGHUP, &act, NULL);
+	sigaction(SIGIO, &act, NULL);
+
+	udev_rules_init(&rules, 1);
+	watch_directory(udev_rules_filename);
 
 	if (init_uevent_netlink_sock() < 0) {
 		dbg("uevent socket not available");
@@ -1010,6 +1086,12 @@ int main(int argc, char *argv[], char *e
 			if (!stop_exec_q)
 				exec_queue_manager();
 		}
+
+		if (reload_config) {
+			reload_config = 0;
+			udev_rules_close(&rules);
+			udev_rules_init(&rules, 1);
+		}
 	}
 
 exit:
diff --git a/udevd.h b/udevd.h
--- a/udevd.h
+++ b/udevd.h
@@ -54,6 +54,7 @@ enum udevd_msg_type {
 	UDEVD_START_EXEC_QUEUE,
 	UDEVD_SET_LOG_LEVEL,
 	UDEVD_SET_MAX_CHILDS,
+	UDEVD_RELOAD_RULES,
 };
 
 

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

* Re: move udev-rules parsing into the daemon
  2005-07-31  0:42 move udev-rules parsing into the daemon Kay Sievers
@ 2005-08-02  2:42 ` Kay Sievers
  2005-08-06  0:39 ` Greg KH
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Kay Sievers @ 2005-08-02  2:42 UTC (permalink / raw)
  To: linux-hotplug

[-- Attachment #1: Type: text/plain, Size: 845 bytes --]

On Sun, Jul 31, 2005 at 02:42:27AM +0200, Kay Sievers wrote:
> Here we move the parsed rules into the udev daemon, which will no longer
> execute the udev binary. This saves us the rule parsing, cause the
> parsed rules will be inherited from the daemon process, which will
> fork() a child which imediately becomes the event process without doing
> an exec(). It's basically a retry of this old patch:
>   http://marc.theaimsgroup.com/?l=linux-hotplug-devel&m=109814301613236&w=2
> 
> Changes to /etc/udev/rules.d/* will automatically recognized and will cause
> a reload of the rules, also the usual -HUP should work.
> 
> Would be nice if someone brave enough can give it a try, we want to put
> that upstream if it works as expected. The patch applies on top of v064.

New patch with a few fixes on top of the current git tree.

Thanks,
Kay

[-- Attachment #2: udevd-noexec-14.patch --]
[-- Type: text/plain, Size: 6635 bytes --]

diff --git a/udevcontrol.c b/udevcontrol.c
--- a/udevcontrol.c
+++ b/udevcontrol.c
@@ -97,7 +97,9 @@ int main(int argc, char *argv[], char *e
 		usend_msg.type = UDEVD_SET_MAX_CHILDS;
 		*intval = atoi(val);
 		info("send max_childs=%i", *intval);
-	} else {
+	} else if (!strcmp(argv[1], "reload_rules"))
+		usend_msg.type = UDEVD_RELOAD_RULES;
+	else {
 		err("error parsing command\n");
 		goto exit;
 	}
diff --git a/udevd.c b/udevd.c
--- a/udevd.c
+++ b/udevd.c
@@ -45,6 +45,7 @@
 #include "udev_libc_wrapper.h"
 #include "udev.h"
 #include "udev_version.h"
+#include "udev_rules.h"
 #include "udev_utils.h"
 #include "udevd.h"
 #include "logging.h"
@@ -54,6 +55,7 @@
 #endif
 
 /* global variables*/
+struct udev_rules rules;
 static int udevd_sock;
 static int uevent_netlink_sock;
 static pid_t sid;
@@ -65,6 +67,7 @@ static volatile int sig_flag;
 static int init_phase = 1;
 static int run_exec_q;
 static int stop_exec_q;
+static int reload_config;
 
 static LIST_HEAD(msg_list);
 static LIST_HEAD(exec_list);
@@ -75,12 +78,13 @@ static void msg_queue_manager(void);
 static void user_sighandler(void);
 static void reap_sigchilds(void);
 
-static char *udev_bin;
 static unsigned long long expected_seqnum;
 static int event_timeout;
 static int max_childs;
 static int max_childs_running;
 
+static char log[32];
+
 
 #ifdef USE_LOG
 void log_message (int priority, const char *format, ...)
@@ -167,10 +171,58 @@ static void msg_queue_insert(struct ueve
 	return;
 }
 
+static void asmlinkage udev_event_sig_handler(int signum)
+{
+	if (signum == SIGALRM)
+		exit(1);
+}
+
+static int udev_event_process(struct uevent_msg *msg)
+{
+	struct sigaction act;
+	struct udevice udev;
+	struct name_entry *name_loop;
+	int i;
+	int retval;
+
+	logging_init("udevd-event");
+
+	/* set signal handlers */
+	memset(&act, 0x00, sizeof(act));
+	act.sa_handler = (void (*)(int)) udev_event_sig_handler;
+	sigemptyset (&act.sa_mask);
+	act.sa_flags = 0;
+	sigaction(SIGALRM, &act, NULL);
+
+	/* trigger timeout to prevent hanging processes */
+	alarm(UDEV_ALARM_TIMEOUT);
+
+	/* reconstruct env from message */
+	for (i = 0; msg->envp[i]; i++)
+		putenv(msg->envp[i]);
+
+	udev_init_device(&udev, msg->devpath, msg->subsystem, msg->action);
+	retval = udev_process_event(&rules, &udev);
+
+	/* run programs collected by RUN-key*/
+	if (!retval) {
+		list_for_each_entry(name_loop, &udev.run_list, node) {
+			if (strncmp(name_loop->name, "socket:", strlen("socket:")) == 0)
+				pass_env_to_socket(&name_loop->name[strlen("socket:")], msg->devpath, msg->action);
+			else
+				execute_program(name_loop->name, udev.subsystem, NULL, 0, NULL);
+		}
+	}
+
+	udev_cleanup_device(&udev);
+	logging_close();
+
+	return 0;
+}
+
 /* forks event and removes event from run queue when finished */
 static void udev_event_fork(struct uevent_msg *msg)
 {
-	char *const argv[] = { "udev", msg->subsystem, NULL };
 	pid_t pid;
 	struct sysinfo info;
 
@@ -183,9 +235,9 @@ static void udev_event_fork(struct ueven
 		close(udevd_sock);
 		logging_close();
 		setpriority(PRIO_PROCESS, 0, UDEV_PRIORITY);
-		execve(udev_bin, argv, msg->envp);
-		err("exec of child failed");
-		_exit(1);
+
+		udev_event_process(msg);
+		exit(0);
 	case -1:
 		err("fork of child failed");
 		msg_queue_delete(msg);
@@ -574,12 +626,19 @@ static struct uevent_msg *get_udevd_msg(
 		intval = (int *) usend_msg.envbuf;
 		info("udevd message (SET_LOG_PRIORITY) received, udev_log_priority=%i", *intval);
 		udev_log_priority = *intval;
+		sprintf(log, "UDEV_LOG=%i", udev_log_priority);
+		putenv(log);
 		break;
 	case UDEVD_SET_MAX_CHILDS:
 		intval = (int *) usend_msg.envbuf;
 		info("udevd message (UDEVD_SET_MAX_CHILDS) received, max_childs=%i", *intval);
 		max_childs = *intval;
 		break;
+	case UDEVD_RELOAD_RULES:
+		info("udevd message (RELOAD_RULES) received");
+		udev_rules_close(&rules);
+		udev_rules_init(&rules, 1);
+		break;
 	default:
 		dbg("unknown message type");
 	}
@@ -650,16 +709,17 @@ static void asmlinkage sig_handler(int s
 		case SIGALRM:
 			/* set flag, then write to pipe if needed */
 			run_msg_q = 1;
-			goto do_write;
 			break;
 		case SIGCHLD:
 			/* set flag, then write to pipe if needed */
 			sigchilds_waiting = 1;
-			goto do_write;
+			break;
+		case SIGHUP:
+		case SIGIO:
+			reload_config = 1;
 			break;
 	}
 
-do_write:
 	/* if pipe is empty, write to pipe to force select to return
 	 * immediately when it gets called
 	 */
@@ -787,6 +847,24 @@ static int init_uevent_netlink_sock(void
 	return 0;
 }
 
+static int watch_directory(const char *dir)
+{
+	int fd;
+
+	fd = open(dir, O_RDONLY);
+	if (fd < 0) {
+		err("could not open '%s' to watch it", dir);
+		return -1;
+	}
+	if (fcntl(fd, F_NOTIFY, DN_MODIFY | DN_CREATE | DN_DELETE | DN_MULTISHOT) == -1) {
+		err("could not set dnotify on '%s'", dir);
+		return -1;
+		close(fd);
+	}
+
+	return 0;
+}
+
 int main(int argc, char *argv[], char *envp[])
 {
 	int maxsockplus;
@@ -891,6 +969,11 @@ int main(int argc, char *argv[], char *e
 	sigaction(SIGTERM, &act, NULL);
 	sigaction(SIGALRM, &act, NULL);
 	sigaction(SIGCHLD, &act, NULL);
+	sigaction(SIGHUP, &act, NULL);
+	sigaction(SIGIO, &act, NULL);
+
+	udev_rules_init(&rules, 1);
+	watch_directory(udev_rules_filename);
 
 	if (init_uevent_netlink_sock() < 0) {
 		dbg("uevent socket not available");
@@ -905,13 +988,6 @@ int main(int argc, char *argv[], char *e
 		goto exit;
 	}
 
-	/* override of forked udev binary, used for testing */
-	udev_bin = getenv("UDEV_BIN");
-	if (udev_bin != NULL)
-		info("udev binary is set to '%s'", udev_bin);
-	else
-		udev_bin = UDEV_BIN;
-
 	/* init of expected_seqnum value */
 	value = getenv("UDEVD_EXPECTED_SEQNUM");
 	if (value) {
@@ -943,6 +1019,13 @@ int main(int argc, char *argv[], char *e
 		max_childs_running = UDEVD_MAX_CHILDS_RUNNING;
 	info("initialize max_childs_running to %u", max_childs_running);
 
+	/* clear environment for forked event processes */
+	clearenv();
+
+	/* export log_priority , as called programs may want to do the same as udev */
+	sprintf(log, "UDEV_LOG=%i", udev_log_priority);
+	putenv(log);
+
 	FD_ZERO(&readfds);
 	FD_SET(udevd_sock, &readfds);
 	if (uevent_netlink_sock != -1)
@@ -1010,6 +1093,12 @@ int main(int argc, char *argv[], char *e
 			if (!stop_exec_q)
 				exec_queue_manager();
 		}
+
+		if (reload_config) {
+			reload_config = 0;
+			udev_rules_close(&rules);
+			udev_rules_init(&rules, 1);
+		}
 	}
 
 exit:
diff --git a/udevd.h b/udevd.h
--- a/udevd.h
+++ b/udevd.h
@@ -54,6 +54,7 @@ enum udevd_msg_type {
 	UDEVD_START_EXEC_QUEUE,
 	UDEVD_SET_LOG_LEVEL,
 	UDEVD_SET_MAX_CHILDS,
+	UDEVD_RELOAD_RULES,
 };
 
 

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

* Re: move udev-rules parsing into the daemon
  2005-07-31  0:42 move udev-rules parsing into the daemon Kay Sievers
  2005-08-02  2:42 ` Kay Sievers
@ 2005-08-06  0:39 ` Greg KH
  2005-08-06  3:41 ` Kay Sievers
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Greg KH @ 2005-08-06  0:39 UTC (permalink / raw)
  To: linux-hotplug

On Tue, Aug 02, 2005 at 04:42:44AM +0200, Kay Sievers wrote:
> +static int watch_directory(const char *dir)
> +{
> +	int fd;
> +
> +	fd = open(dir, O_RDONLY);
> +	if (fd < 0) {
> +		err("could not open '%s' to watch it", dir);
> +		return -1;
> +	}
> +	if (fcntl(fd, F_NOTIFY, DN_MODIFY | DN_CREATE | DN_DELETE | DN_MULTISHOT) = -1) {
> +		err("could not set dnotify on '%s'", dir);
> +		return -1;
> +		close(fd);
> +	}
> +
> +	return 0;
> +}

Why dnotify and not inotify?

thanks,

greg k-h


-------------------------------------------------------
SF.Net email is Sponsored by the Better Software Conference & EXPO
September 19-22, 2005 * San Francisco, CA * Development Lifecycle Practices
Agile & Plan-Driven Development * Managing Projects & Teams * Testing & QA
Security * Process Improvement & Measurement * http://www.sqe.com/bsce5sf
_______________________________________________
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

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

* Re: move udev-rules parsing into the daemon
  2005-07-31  0:42 move udev-rules parsing into the daemon Kay Sievers
  2005-08-02  2:42 ` Kay Sievers
  2005-08-06  0:39 ` Greg KH
@ 2005-08-06  3:41 ` Kay Sievers
  2005-08-09  2:30 ` Kay Sievers
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Kay Sievers @ 2005-08-06  3:41 UTC (permalink / raw)
  To: linux-hotplug

On Fri, Aug 05, 2005 at 05:39:52PM -0700, Greg KH wrote:
> On Tue, Aug 02, 2005 at 04:42:44AM +0200, Kay Sievers wrote:
> > +static int watch_directory(const char *dir)
> > +{
> > +	int fd;
> > +
> > +	fd = open(dir, O_RDONLY);
> > +	if (fd < 0) {
> > +		err("could not open '%s' to watch it", dir);
> > +		return -1;
> > +	}
> > +	if (fcntl(fd, F_NOTIFY, DN_MODIFY | DN_CREATE | DN_DELETE | DN_MULTISHOT) = -1) {
> > +		err("could not set dnotify on '%s'", dir);
> > +		return -1;
> > +		close(fd);
> > +	}
> > +
> > +	return 0;
> > +}
> 
> Why dnotify and not inotify?

The patch is just older than inotify is in mainline. :)
If we can require the latest kernel, I will happily change it.

Thanks,
Kay


-------------------------------------------------------
SF.Net email is Sponsored by the Better Software Conference & EXPO
September 19-22, 2005 * San Francisco, CA * Development Lifecycle Practices
Agile & Plan-Driven Development * Managing Projects & Teams * Testing & QA
Security * Process Improvement & Measurement * http://www.sqe.com/bsce5sf
_______________________________________________
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

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

* Re: move udev-rules parsing into the daemon
  2005-07-31  0:42 move udev-rules parsing into the daemon Kay Sievers
                   ` (2 preceding siblings ...)
  2005-08-06  3:41 ` Kay Sievers
@ 2005-08-09  2:30 ` Kay Sievers
  2005-08-11  6:13 ` Greg KH
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Kay Sievers @ 2005-08-09  2:30 UTC (permalink / raw)
  To: linux-hotplug

[-- Attachment #1: Type: text/plain, Size: 1022 bytes --]

On Sat, Aug 06, 2005 at 05:41:06AM +0200, Kay Sievers wrote:
> On Fri, Aug 05, 2005 at 05:39:52PM -0700, Greg KH wrote:
> > On Tue, Aug 02, 2005 at 04:42:44AM +0200, Kay Sievers wrote:
> > > +static int watch_directory(const char *dir)
> > > +{
> > > +	int fd;
> > > +
> > > +	fd = open(dir, O_RDONLY);
> > > +	if (fd < 0) {
> > > +		err("could not open '%s' to watch it", dir);
> > > +		return -1;
> > > +	}
> > > +	if (fcntl(fd, F_NOTIFY, DN_MODIFY | DN_CREATE | DN_DELETE | DN_MULTISHOT) == -1) {
> > > +		err("could not set dnotify on '%s'", dir);
> > > +		return -1;
> > > +		close(fd);
> > > +	}
> > > +
> > > +	return 0;
> > > +}
> > 
> > Why dnotify and not inotify?
> 
> The patch is just older than inotify is in mainline. :)
> If we can require the latest kernel, I will happily change it.

Here we go with the Inotify version on top of the current tree.
I've added some stuff to our libc-wrapper file until the inotify
headers have reached glibc and we can just add an #include to
udevd.c for it.

Thanks,
Kay

[-- Attachment #2: udevd-noexec-inotify-04.patch --]
[-- Type: text/plain, Size: 11131 bytes --]

diff --git a/Makefile b/Makefile
diff --git a/klibc/klibc/SYSCALLS.def b/klibc/klibc/SYSCALLS.def
--- a/klibc/klibc/SYSCALLS.def
+++ b/klibc/klibc/SYSCALLS.def
@@ -114,6 +114,9 @@ int lchown32,lchown::lchown(const char *
 int getcwd::__getcwd(char *, size_t)
 <?> int utime(const char *, const struct utimbuf *)
 <?> int utimes(const char *, const struct timeval *)
+<?> int inotify_init(void)
+<?> int inotify_add_watch(int, const char *, __u32)
+<?> int inotify_rm_watch(int, __u32)
 
 ;
 ; I/O operations
diff --git a/udev_libc_wrapper.h b/udev_libc_wrapper.h
--- a/udev_libc_wrapper.h
+++ b/udev_libc_wrapper.h
@@ -22,6 +22,53 @@
 #ifndef _UDEV_LIBC_WRAPPER_H_
 #define _UDEV_LIBC_WRAPPER_H_
 
+#include <string.h>
+#include <linux/unistd.h>
+#include <linux/types.h>
+
+/* needed until it reaches libc */
+#ifndef __NR_inotify_init
+#if defined(__i386__)
+# define __NR_inotify_init      291
+# define __NR_inotify_add_watch 292
+# define __NR_inotify_rm_watch  293
+#elif defined(__x86_64__)
+# define __NR_inotify_init      253
+# define __NR_inotify_add_watch 254
+# define __NR_inotify_rm_watch  255
+#elif defined(__ppc__)
+# define __NR_inotify_init      275
+# define __NR_inotify_add_watch 276
+# define __NR_inotify_rm_watch  277
+#elif defined (__ia64__)
+# define __NR_inotify_init      1277
+# define __NR_inotify_add_watch 1278
+# define __NR_inotify_rm_watch  1279
+#elif defined (__s390__)
+# define __NR_inotify_init      284
+# define __NR_inotify_add_watch 285
+# define __NR_inotify_rm_watch  286
+#else
+# error "Unsupported architecture!"
+#endif
+static inline _syscall0(int, inotify_init);
+static inline _syscall3(int, inotify_add_watch, int, fd, const char*, name, __u32, mask);
+#else
+extern int inotify_init(void);
+extern int inotify_add_watch (int fd, const char *name, __u32 mask);
+#endif /* __NR_inotify_init */
+
+/* needed until it reaches libc kernel headers */
+#ifndef IN_MODIFY
+#define IN_MODIFY		0x00000002	/* File was modified */
+#define IN_MOVED_FROM		0x00000040	/* File was moved from X */
+#define IN_MOVED_TO		0x00000080	/* File was moved to Y */
+#define IN_CREATE		0x00000100	/* Subfile was created */
+#define IN_DELETE		0x00000200	/* Subfile was deleted */
+#define IN_MOVE			(IN_MOVED_FROM | IN_MOVED_TO) /* moves */
+#endif
+
+/* needed for our signal handlers to work */
 #undef asmlinkage
 #ifdef __i386__
 #define asmlinkage	__attribute__((regparm(0)))
@@ -29,6 +76,7 @@
 #define asmlinkage
 #endif
 
+/* headers are broken on some lazy platforms */
 #ifndef __FD_SET
 #define __FD_SET(d, set) ((set)->fds_bits[__FDELT(d)] |= __FDMASK(d))
 #endif
@@ -42,12 +90,11 @@
 #define __FD_ZERO(set) ((void) memset ((void*) (set), 0, sizeof (fd_set)))
 #endif
 
+/* missing in some lazy distros */
 #ifndef NETLINK_KOBJECT_UEVENT
 #define NETLINK_KOBJECT_UEVENT 15
 #endif
 
-#include <string.h>
-
 #ifdef __KLIBC__
 static inline int clearenv(void)
 {
diff --git a/udevcontrol.c b/udevcontrol.c
--- a/udevcontrol.c
+++ b/udevcontrol.c
@@ -97,7 +97,9 @@ int main(int argc, char *argv[], char *e
 		usend_msg.type = UDEVD_SET_MAX_CHILDS;
 		*intval = atoi(val);
 		info("send max_childs=%i", *intval);
-	} else {
+	} else if (!strcmp(argv[1], "reload_rules"))
+		usend_msg.type = UDEVD_RELOAD_RULES;
+	else {
 		err("error parsing command\n");
 		goto exit;
 	}
diff --git a/udevd.c b/udevd.c
--- a/udevd.c
+++ b/udevd.c
@@ -38,6 +38,7 @@
 #include <sys/un.h>
 #include <sys/sysinfo.h>
 #include <sys/stat.h>
+#include <sys/ioctl.h>
 #include <linux/types.h>
 #include <linux/netlink.h>
 
@@ -45,13 +46,16 @@
 #include "udev_libc_wrapper.h"
 #include "udev.h"
 #include "udev_version.h"
+#include "udev_rules.h"
 #include "udev_utils.h"
 #include "udevd.h"
 #include "logging.h"
 
 /* global variables*/
+struct udev_rules rules;
 static int udevd_sock;
 static int uevent_netlink_sock;
+static int inotify_fd;
 static pid_t sid;
 
 static int pipefds[2];
@@ -59,6 +63,7 @@ static volatile int sigchilds_waiting;
 static volatile int run_msg_q;
 static volatile int sig_flag;
 static volatile int udev_exit;
+static volatile int reload_config;
 static int init_phase = 1;
 static int run_exec_q;
 static int stop_exec_q;
@@ -72,12 +77,13 @@ static void msg_queue_manager(void);
 static void user_sighandler(void);
 static void reap_sigchilds(void);
 
-static char *udev_bin;
 static unsigned long long expected_seqnum;
 static int event_timeout;
 static int max_childs;
 static int max_childs_running;
 
+static char log[32];
+
 
 #ifdef USE_LOG
 void log_message (int priority, const char *format, ...)
@@ -164,10 +170,58 @@ static void msg_queue_insert(struct ueve
 	return;
 }
 
+static void asmlinkage udev_event_sig_handler(int signum)
+{
+	if (signum == SIGALRM)
+		exit(1);
+}
+
+static int udev_event_process(struct uevent_msg *msg)
+{
+	struct sigaction act;
+	struct udevice udev;
+	struct name_entry *name_loop;
+	int i;
+	int retval;
+
+	logging_init("udevd-event");
+
+	/* set signal handlers */
+	memset(&act, 0x00, sizeof(act));
+	act.sa_handler = (void (*)(int)) udev_event_sig_handler;
+	sigemptyset (&act.sa_mask);
+	act.sa_flags = 0;
+	sigaction(SIGALRM, &act, NULL);
+
+	/* trigger timeout to prevent hanging processes */
+	alarm(UDEV_ALARM_TIMEOUT);
+
+	/* reconstruct env from message */
+	for (i = 0; msg->envp[i]; i++)
+		putenv(msg->envp[i]);
+
+	udev_init_device(&udev, msg->devpath, msg->subsystem, msg->action);
+	retval = udev_process_event(&rules, &udev);
+
+	/* run programs collected by RUN-key*/
+	if (!retval) {
+		list_for_each_entry(name_loop, &udev.run_list, node) {
+			if (strncmp(name_loop->name, "socket:", strlen("socket:")) == 0)
+				pass_env_to_socket(&name_loop->name[strlen("socket:")], msg->devpath, msg->action);
+			else
+				execute_program(name_loop->name, udev.subsystem, NULL, 0, NULL);
+		}
+	}
+
+	udev_cleanup_device(&udev);
+	logging_close();
+
+	return 0;
+}
+
 /* forks event and removes event from run queue when finished */
 static void udev_event_fork(struct uevent_msg *msg)
 {
-	char *const argv[] = { "udev", msg->subsystem, NULL };
 	pid_t pid;
 	struct sysinfo info;
 
@@ -180,9 +234,9 @@ static void udev_event_fork(struct ueven
 		close(udevd_sock);
 		logging_close();
 		setpriority(PRIO_PROCESS, 0, UDEV_PRIORITY);
-		execve(udev_bin, argv, msg->envp);
-		err("exec of child failed");
-		_exit(1);
+
+		udev_event_process(msg);
+		exit(0);
 	case -1:
 		err("fork of child failed");
 		msg_queue_delete(msg);
@@ -441,7 +495,7 @@ recheck:
 	msg_dump_queue();
 
 	/* set timeout for remaining queued events */
-	if (list_empty(&msg_list) == 0) {
+	if (!list_empty(&msg_list)) {
 		struct itimerval itv = {{0, 0}, {timeout - msg_age, 0}};
 		dbg("next event expires in %li seconds", timeout - msg_age);
 		setitimer(ITIMER_REAL, &itv, NULL);
@@ -571,12 +625,19 @@ static struct uevent_msg *get_udevd_msg(
 		intval = (int *) usend_msg.envbuf;
 		info("udevd message (SET_LOG_PRIORITY) received, udev_log_priority=%i", *intval);
 		udev_log_priority = *intval;
+		sprintf(log, "UDEV_LOG=%i", udev_log_priority);
+		putenv(log);
 		break;
 	case UDEVD_SET_MAX_CHILDS:
 		intval = (int *) usend_msg.envbuf;
 		info("udevd message (UDEVD_SET_MAX_CHILDS) received, max_childs=%i", *intval);
 		max_childs = *intval;
 		break;
+	case UDEVD_RELOAD_RULES:
+		info("udevd message (RELOAD_RULES) received");
+		udev_rules_close(&rules);
+		udev_rules_init(&rules, 0, 1);
+		break;
 	default:
 		dbg("unknown message type");
 	}
@@ -652,6 +713,9 @@ static void asmlinkage sig_handler(int s
 			/* set flag, then write to pipe if needed */
 			sigchilds_waiting = 1;
 			break;
+		case SIGHUP:
+			reload_config = 1;
+			break;
 	}
 
 	/* if pipe is empty, write to pipe to force select to return,
@@ -813,6 +877,7 @@ int main(int argc, char *argv[], char *e
 			stop_exec_q = 1;
 		}
 	}
+
 	if (daemonize) {
 		pid_t pid;
 
@@ -887,9 +952,11 @@ int main(int argc, char *argv[], char *e
 	sigaction(SIGCHLD, &act, NULL);
 	sigaction(SIGHUP, &act, NULL);
 
+	udev_rules_init(&rules, 0, 1);
+
 	if (init_uevent_netlink_sock() < 0) {
 		dbg("uevent socket not available");
- 	}
+	}
 
 	if (init_udevd_socket() < 0) {
 		if (errno == EADDRINUSE)
@@ -900,12 +967,10 @@ int main(int argc, char *argv[], char *e
 		goto exit;
 	}
 
-	/* override of forked udev binary, used for testing */
-	udev_bin = getenv("UDEV_BIN");
-	if (udev_bin != NULL)
-		info("udev binary is set to '%s'", udev_bin);
-	else
-		udev_bin = UDEV_BIN;
+	/* watch config directory */
+	inotify_fd = inotify_init();
+	if (inotify_fd > 0)
+		inotify_add_watch(inotify_fd, udev_rules_filename, IN_CREATE | IN_DELETE | IN_MOVE | IN_MODIFY);
 
 	/* init of expected_seqnum value */
 	value = getenv("UDEVD_EXPECTED_SEQNUM");
@@ -938,18 +1003,28 @@ int main(int argc, char *argv[], char *e
 		max_childs_running = UDEVD_MAX_CHILDS_RUNNING;
 	info("initialize max_childs_running to %u", max_childs_running);
 
+	/* clear environment for forked event processes */
+	clearenv();
+
+	/* export log_priority , as called programs may want to do the same as udev */
+	sprintf(log, "UDEV_LOG=%i", udev_log_priority);
+	putenv(log);
+
+	/* prepare list of file descriptors to watch */
 	FD_ZERO(&readfds);
 	FD_SET(udevd_sock, &readfds);
 	if (uevent_netlink_sock > 0)
 		FD_SET(uevent_netlink_sock, &readfds);
+	if (inotify_fd > 0)
+		FD_SET(inotify_fd, &readfds);
 	FD_SET(pipefds[0], &readfds);
-	maxsockplus = udevd_sock+1;
+	maxsockplus = inotify_fd+1;
+
 	while (!udev_exit) {
 		struct uevent_msg *msg;
 
 		fd_set workreadfds = readfds;
 		retval = select(maxsockplus, &workreadfds, NULL, NULL, NULL);
-
 		if (retval < 0) {
 			if (errno != EINTR)
 				dbg("error in select: %s", strerror(errno));
@@ -983,10 +1058,37 @@ int main(int argc, char *argv[], char *e
 			}
 		}
 
+		/* rules directory inotify message */
+		if (FD_ISSET(inotify_fd, &workreadfds)) {
+			int nbytes;
+
+			/* discard all possible events, we can just reload the config at any event */
+			if ((ioctl(inotify_fd, FIONREAD, &nbytes) == 0) && nbytes) {
+				char *buf;
+
+				reload_config = 1;
+				buf = malloc(nbytes);
+				if (!buf) {
+					err("error getting buffer for inotify, disable watching");
+					close(inotify_fd);
+					inotify_fd = -1;
+				}
+				read(inotify_fd, buf, nbytes);
+				free(buf);
+			}
+		}
+
 		/* received a signal, clear our notification pipe */
 		if (FD_ISSET(pipefds[0], &workreadfds))
 			user_sighandler();
 
+		/* set by inotify or a signal*/
+		if (reload_config) {
+			reload_config = 0;
+			udev_rules_close(&rules);
+			udev_rules_init(&rules, 0, 1);
+		}
+
 		/* forked child have returned */
 		if (sigchilds_waiting) {
 			sigchilds_waiting = 0;
@@ -1012,12 +1114,13 @@ int main(int argc, char *argv[], char *e
 	}
 
 exit:
+	udev_rules_close(&rules);
 	if (udevd_sock > 0)
 		close(udevd_sock);
-
 	if (uevent_netlink_sock > 0)
 		close(uevent_netlink_sock);
-
+	if (inotify_fd > 0)
+		close(inotify_fd);
 	logging_close();
 
 	return 0;
diff --git a/udevd.h b/udevd.h
--- a/udevd.h
+++ b/udevd.h
@@ -54,6 +54,7 @@ enum udevd_msg_type {
 	UDEVD_START_EXEC_QUEUE,
 	UDEVD_SET_LOG_LEVEL,
 	UDEVD_SET_MAX_CHILDS,
+	UDEVD_RELOAD_RULES,
 };
 
 

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

* Re: move udev-rules parsing into the daemon
  2005-07-31  0:42 move udev-rules parsing into the daemon Kay Sievers
                   ` (3 preceding siblings ...)
  2005-08-09  2:30 ` Kay Sievers
@ 2005-08-11  6:13 ` Greg KH
  2005-08-11 23:06 ` Kay Sievers
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Greg KH @ 2005-08-11  6:13 UTC (permalink / raw)
  To: linux-hotplug

On Tue, Aug 09, 2005 at 04:30:07AM +0200, Kay Sievers wrote:
> Here we go with the Inotify version on top of the current tree.
> I've added some stuff to our libc-wrapper file until the inotify
> headers have reached glibc and we can just add an #include to
> udevd.c for it.

Looks good to me.

greg k-h


-------------------------------------------------------
SF.Net email is Sponsored by the Better Software Conference & EXPO
September 19-22, 2005 * San Francisco, CA * Development Lifecycle Practices
Agile & Plan-Driven Development * Managing Projects & Teams * Testing & QA
Security * Process Improvement & Measurement * http://www.sqe.com/bsce5sf
_______________________________________________
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

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

* Re: move udev-rules parsing into the daemon
  2005-07-31  0:42 move udev-rules parsing into the daemon Kay Sievers
                   ` (4 preceding siblings ...)
  2005-08-11  6:13 ` Greg KH
@ 2005-08-11 23:06 ` Kay Sievers
  2005-08-12  2:49 ` Kay Sievers
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Kay Sievers @ 2005-08-11 23:06 UTC (permalink / raw)
  To: linux-hotplug

[-- Attachment #1: Type: text/plain, Size: 421 bytes --]

On Wed, Aug 10, 2005 at 11:13:14PM -0700, Greg KH wrote:
> On Tue, Aug 09, 2005 at 04:30:07AM +0200, Kay Sievers wrote:
> > Here we go with the Inotify version on top of the current tree.
> > I've added some stuff to our libc-wrapper file until the inotify
> > headers have reached glibc and we can just add an #include to
> > udevd.c for it.
> 
> Looks good to me.

Here is a version on top of the new 066.

Thanks,
Kay

[-- Attachment #2: udevd-noexec-inotify-07.patch --]
[-- Type: text/plain, Size: 11952 bytes --]

diff --git a/klibc/klibc/SYSCALLS.def b/klibc/klibc/SYSCALLS.def
--- a/klibc/klibc/SYSCALLS.def
+++ b/klibc/klibc/SYSCALLS.def
@@ -114,6 +114,9 @@ int lchown32,lchown::lchown(const char *
 int getcwd::__getcwd(char *, size_t)
 <?> int utime(const char *, const struct utimbuf *)
 <?> int utimes(const char *, const struct timeval *)
+<?> int inotify_init(void)
+<?> int inotify_add_watch(int, const char *, __u32)
+<?> int inotify_rm_watch(int, __u32)
 
 ;
 ; I/O operations
diff --git a/udev_libc_wrapper.h b/udev_libc_wrapper.h
--- a/udev_libc_wrapper.h
+++ b/udev_libc_wrapper.h
@@ -22,6 +22,53 @@
 #ifndef _UDEV_LIBC_WRAPPER_H_
 #define _UDEV_LIBC_WRAPPER_H_
 
+#include <string.h>
+#include <linux/unistd.h>
+#include <linux/types.h>
+
+/* needed until it reaches libc */
+#ifndef __NR_inotify_init
+#if defined(__i386__)
+# define __NR_inotify_init      291
+# define __NR_inotify_add_watch 292
+# define __NR_inotify_rm_watch  293
+#elif defined(__x86_64__)
+# define __NR_inotify_init      253
+# define __NR_inotify_add_watch 254
+# define __NR_inotify_rm_watch  255
+#elif defined(__ppc__)
+# define __NR_inotify_init      275
+# define __NR_inotify_add_watch 276
+# define __NR_inotify_rm_watch  277
+#elif defined (__ia64__)
+# define __NR_inotify_init      1277
+# define __NR_inotify_add_watch 1278
+# define __NR_inotify_rm_watch  1279
+#elif defined (__s390__)
+# define __NR_inotify_init      284
+# define __NR_inotify_add_watch 285
+# define __NR_inotify_rm_watch  286
+#else
+# error "Unsupported architecture!"
+#endif
+static inline _syscall0(int, inotify_init);
+static inline _syscall3(int, inotify_add_watch, int, fd, const char*, name, __u32, mask);
+#else
+extern int inotify_init(void);
+extern int inotify_add_watch (int fd, const char *name, __u32 mask);
+#endif /* __NR_inotify_init */
+
+/* needed until it reaches libc kernel headers */
+#ifndef IN_MODIFY
+#define IN_MODIFY		0x00000002	/* File was modified */
+#define IN_MOVED_FROM		0x00000040	/* File was moved from X */
+#define IN_MOVED_TO		0x00000080	/* File was moved to Y */
+#define IN_CREATE		0x00000100	/* Subfile was created */
+#define IN_DELETE		0x00000200	/* Subfile was deleted */
+#define IN_MOVE			(IN_MOVED_FROM | IN_MOVED_TO) /* moves */
+#endif
+
+/* needed for our signal handlers to work */
 #undef asmlinkage
 #ifdef __i386__
 #define asmlinkage	__attribute__((regparm(0)))
@@ -29,6 +76,7 @@
 #define asmlinkage
 #endif
 
+/* headers are broken on some lazy platforms */
 #ifndef __FD_SET
 #define __FD_SET(d, set) ((set)->fds_bits[__FDELT(d)] |= __FDMASK(d))
 #endif
@@ -42,12 +90,11 @@
 #define __FD_ZERO(set) ((void) memset ((void*) (set), 0, sizeof (fd_set)))
 #endif
 
+/* missing in some lazy distros */
 #ifndef NETLINK_KOBJECT_UEVENT
 #define NETLINK_KOBJECT_UEVENT 15
 #endif
 
-#include <string.h>
-
 #ifdef __KLIBC__
 static inline int clearenv(void)
 {
diff --git a/udevcontrol.c b/udevcontrol.c
--- a/udevcontrol.c
+++ b/udevcontrol.c
@@ -89,6 +89,8 @@ int main(int argc, char *argv[], char *e
 			usend_msg.type = UDEVD_STOP_EXEC_QUEUE;
 		else if (!strcmp(arg, "start_exec_queue"))
 			usend_msg.type = UDEVD_START_EXEC_QUEUE;
+		else if (!strcmp(arg, "reload_rules"))
+			usend_msg.type = UDEVD_RELOAD_RULES;
 		else if (!strncmp(arg, "log_priority=", strlen("log_priority="))) {
 			intval = (int *) usend_msg.envbuf;
 			val = &arg[strlen("log_priority=")];
@@ -106,6 +108,7 @@ int main(int argc, char *argv[], char *e
 				"  log_priority=<level> set the udev log level for the daemon\n"
 				"  stop_exec_queue      keep udevd from executing events, queue only\n"
 				"  start_exec_queue     execute events, flush queue\n"
+				"  reload_rules         reloads the rules files\n"
 				"  max_childs=<N>       maximum number of childs running at the same time\n"
 				"  --help               print this help text\n\n");
 			exit(0);
diff --git a/udevd.c b/udevd.c
--- a/udevd.c
+++ b/udevd.c
@@ -30,6 +30,7 @@
 #include <ctype.h>
 #include <dirent.h>
 #include <fcntl.h>
+#include <syslog.h>
 #include <sys/select.h>
 #include <sys/wait.h>
 #include <sys/time.h>
@@ -38,6 +39,7 @@
 #include <sys/un.h>
 #include <sys/sysinfo.h>
 #include <sys/stat.h>
+#include <sys/ioctl.h>
 #include <linux/types.h>
 #include <linux/netlink.h>
 
@@ -45,13 +47,16 @@
 #include "udev_libc_wrapper.h"
 #include "udev.h"
 #include "udev_version.h"
+#include "udev_rules.h"
 #include "udev_utils.h"
 #include "udevd.h"
 #include "logging.h"
 
 /* global variables*/
+struct udev_rules rules;
 static int udevd_sock;
 static int uevent_netlink_sock;
+static int inotify_fd;
 static pid_t sid;
 
 static int pipefds[2] = {-1, -1};
@@ -59,6 +64,7 @@ static volatile int sigchilds_waiting;
 static volatile int run_msg_q;
 static volatile int sig_flag;
 static volatile int udev_exit;
+static volatile int reload_config;
 static int init_phase = 1;
 static int run_exec_q;
 static int stop_exec_q;
@@ -72,12 +78,13 @@ static void msg_queue_manager(void);
 static void user_sighandler(void);
 static void reap_sigchilds(void);
 
-static char *udev_bin;
 static unsigned long long expected_seqnum;
 static int event_timeout;
 static int max_childs;
 static int max_childs_running;
 
+static char log[32];
+
 
 #ifdef USE_LOG
 void log_message (int priority, const char *format, ...)
@@ -164,10 +171,58 @@ static void msg_queue_insert(struct ueve
 	return;
 }
 
+static void asmlinkage udev_event_sig_handler(int signum)
+{
+	if (signum == SIGALRM)
+		exit(1);
+}
+
+static int udev_event_process(struct uevent_msg *msg)
+{
+	struct sigaction act;
+	struct udevice udev;
+	struct name_entry *name_loop;
+	int i;
+	int retval;
+
+	logging_init("udevd-event");
+
+	/* set signal handlers */
+	memset(&act, 0x00, sizeof(act));
+	act.sa_handler = (void (*)(int)) udev_event_sig_handler;
+	sigemptyset (&act.sa_mask);
+	act.sa_flags = 0;
+	sigaction(SIGALRM, &act, NULL);
+
+	/* trigger timeout to prevent hanging processes */
+	alarm(UDEV_ALARM_TIMEOUT);
+
+	/* reconstruct env from message */
+	for (i = 0; msg->envp[i]; i++)
+		putenv(msg->envp[i]);
+
+	udev_init_device(&udev, msg->devpath, msg->subsystem, msg->action);
+	retval = udev_process_event(&rules, &udev);
+
+	/* run programs collected by RUN-key*/
+	if (!retval) {
+		list_for_each_entry(name_loop, &udev.run_list, node) {
+			if (strncmp(name_loop->name, "socket:", strlen("socket:")) == 0)
+				pass_env_to_socket(&name_loop->name[strlen("socket:")], msg->devpath, msg->action);
+			else
+				run_program(name_loop->name, udev.subsystem, NULL, 0, NULL, (udev_log_priority >= LOG_DEBUG));
+		}
+	}
+
+	udev_cleanup_device(&udev);
+	logging_close();
+
+	return 0;
+}
+
 /* forks event and removes event from run queue when finished */
 static void udev_event_fork(struct uevent_msg *msg)
 {
-	char *const argv[] = { "udev", msg->subsystem, NULL };
 	pid_t pid;
 	struct sysinfo info;
 
@@ -180,9 +235,9 @@ static void udev_event_fork(struct ueven
 		close(udevd_sock);
 		logging_close();
 		setpriority(PRIO_PROCESS, 0, UDEV_PRIORITY);
-		execve(udev_bin, argv, msg->envp);
-		err("exec of child failed");
-		_exit(1);
+
+		udev_event_process(msg);
+		exit(0);
 	case -1:
 		err("fork of child failed");
 		msg_queue_delete(msg);
@@ -441,7 +496,7 @@ recheck:
 	msg_dump_queue();
 
 	/* set timeout for remaining queued events */
-	if (list_empty(&msg_list) == 0) {
+	if (!list_empty(&msg_list)) {
 		struct itimerval itv = {{0, 0}, {timeout - msg_age, 0}};
 		dbg("next event expires in %li seconds", timeout - msg_age);
 		setitimer(ITIMER_REAL, &itv, NULL);
@@ -571,12 +626,19 @@ static struct uevent_msg *get_udevd_msg(
 		intval = (int *) usend_msg.envbuf;
 		info("udevd message (SET_LOG_PRIORITY) received, udev_log_priority=%i", *intval);
 		udev_log_priority = *intval;
+		sprintf(log, "UDEV_LOG=%i", udev_log_priority);
+		putenv(log);
 		break;
 	case UDEVD_SET_MAX_CHILDS:
 		intval = (int *) usend_msg.envbuf;
 		info("udevd message (UDEVD_SET_MAX_CHILDS) received, max_childs=%i", *intval);
 		max_childs = *intval;
 		break;
+	case UDEVD_RELOAD_RULES:
+		info("udevd message (RELOAD_RULES) received");
+		udev_rules_close(&rules);
+		udev_rules_init(&rules, 0, 1);
+		break;
 	default:
 		dbg("unknown message type");
 	}
@@ -652,6 +714,9 @@ static void asmlinkage sig_handler(int s
 			/* set flag, then write to pipe if needed */
 			sigchilds_waiting = 1;
 			break;
+		case SIGHUP:
+			reload_config = 1;
+			break;
 	}
 
 	/* if pipe is empty, write to pipe to force select to return,
@@ -813,6 +878,7 @@ int main(int argc, char *argv[], char *e
 			stop_exec_q = 1;
 		}
 	}
+
 	if (daemonize) {
 		pid_t pid;
 
@@ -886,9 +952,11 @@ int main(int argc, char *argv[], char *e
 	sigaction(SIGCHLD, &act, NULL);
 	sigaction(SIGHUP, &act, NULL);
 
+	udev_rules_init(&rules, 0, 1);
+
 	if (init_uevent_netlink_sock() < 0) {
 		dbg("uevent socket not available");
- 	}
+	}
 
 	if (init_udevd_socket() < 0) {
 		if (errno == EADDRINUSE)
@@ -899,12 +967,10 @@ int main(int argc, char *argv[], char *e
 		goto exit;
 	}
 
-	/* override of forked udev binary, used for testing */
-	udev_bin = getenv("UDEV_BIN");
-	if (udev_bin != NULL)
-		info("udev binary is set to '%s'", udev_bin);
-	else
-		udev_bin = UDEV_BIN;
+	/* watch config directory */
+	inotify_fd = inotify_init();
+	if (inotify_fd > 0)
+		inotify_add_watch(inotify_fd, udev_rules_filename, IN_CREATE | IN_DELETE | IN_MOVE | IN_MODIFY);
 
 	/* init of expected_seqnum value */
 	value = getenv("UDEVD_EXPECTED_SEQNUM");
@@ -937,18 +1003,28 @@ int main(int argc, char *argv[], char *e
 		max_childs_running = UDEVD_MAX_CHILDS_RUNNING;
 	info("initialize max_childs_running to %u", max_childs_running);
 
+	/* clear environment for forked event processes */
+	clearenv();
+
+	/* export log_priority , as called programs may want to do the same as udev */
+	sprintf(log, "UDEV_LOG=%i", udev_log_priority);
+	putenv(log);
+
+	/* prepare list of file descriptors to watch */
 	FD_ZERO(&readfds);
 	FD_SET(udevd_sock, &readfds);
 	if (uevent_netlink_sock > 0)
 		FD_SET(uevent_netlink_sock, &readfds);
+	if (inotify_fd > 0)
+		FD_SET(inotify_fd, &readfds);
 	FD_SET(pipefds[0], &readfds);
-	maxsockplus = udevd_sock+1;
+	maxsockplus = inotify_fd+1;
+
 	while (!udev_exit) {
 		struct uevent_msg *msg;
 
 		fd_set workreadfds = readfds;
 		retval = select(maxsockplus, &workreadfds, NULL, NULL, NULL);
-
 		if (retval < 0) {
 			if (errno != EINTR)
 				dbg("error in select: %s", strerror(errno));
@@ -982,10 +1058,37 @@ int main(int argc, char *argv[], char *e
 			}
 		}
 
+		/* rules directory inotify message */
+		if (FD_ISSET(inotify_fd, &workreadfds)) {
+			int nbytes;
+
+			/* discard all possible events, we can just reload the config at any event */
+			if ((ioctl(inotify_fd, FIONREAD, &nbytes) == 0) && nbytes) {
+				char *buf;
+
+				reload_config = 1;
+				buf = malloc(nbytes);
+				if (!buf) {
+					err("error getting buffer for inotify, disable watching");
+					close(inotify_fd);
+					inotify_fd = -1;
+				}
+				read(inotify_fd, buf, nbytes);
+				free(buf);
+			}
+		}
+
 		/* received a signal, clear our notification pipe */
 		if (FD_ISSET(pipefds[0], &workreadfds))
 			user_sighandler();
 
+		/* set by inotify or a signal*/
+		if (reload_config) {
+			reload_config = 0;
+			udev_rules_close(&rules);
+			udev_rules_init(&rules, 0, 1);
+		}
+
 		/* forked child have returned */
 		if (sigchilds_waiting) {
 			sigchilds_waiting = 0;
@@ -1011,6 +1114,8 @@ int main(int argc, char *argv[], char *e
 	}
 
 exit:
+	udev_rules_close(&rules);
+
 	if (pipefds[0] > 0)
 		close(pipefds[0]);
 	if (pipefds[1] > 0)
@@ -1018,7 +1123,8 @@ exit:
 
 	if (udevd_sock > 0)
 		close(udevd_sock);
-
+	if (inotify_fd > 0)
+		close(inotify_fd);
 	if (uevent_netlink_sock > 0)
 		close(uevent_netlink_sock);
 
diff --git a/udevd.h b/udevd.h
--- a/udevd.h
+++ b/udevd.h
@@ -54,6 +54,7 @@ enum udevd_msg_type {
 	UDEVD_START_EXEC_QUEUE,
 	UDEVD_SET_LOG_LEVEL,
 	UDEVD_SET_MAX_CHILDS,
+	UDEVD_RELOAD_RULES,
 };
 
 

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

* Re: move udev-rules parsing into the daemon
  2005-07-31  0:42 move udev-rules parsing into the daemon Kay Sievers
                   ` (5 preceding siblings ...)
  2005-08-11 23:06 ` Kay Sievers
@ 2005-08-12  2:49 ` Kay Sievers
  2005-08-12 18:04 ` Greg KH
  2005-08-18 19:23 ` Kay Sievers
  8 siblings, 0 replies; 10+ messages in thread
From: Kay Sievers @ 2005-08-12  2:49 UTC (permalink / raw)
  To: linux-hotplug

[-- Attachment #1: Type: text/plain, Size: 610 bytes --]

On Fri, Aug 12, 2005 at 01:06:24AM +0200, Kay Sievers wrote:
> On Wed, Aug 10, 2005 at 11:13:14PM -0700, Greg KH wrote:
> > On Tue, Aug 09, 2005 at 04:30:07AM +0200, Kay Sievers wrote:
> > > Here we go with the Inotify version on top of the current tree.
> > > I've added some stuff to our libc-wrapper file until the inotify
> > > headers have reached glibc and we can just add an #include to
> > > udevd.c for it.
> > 
> > Looks good to me.
> 
> Here is a version on top of the new 066.

New version to compile successfully with glibc and klibc on:
  i386, x86_64, ppc, ppc64, ia64, s390, s390x

Thanks,
Kay

[-- Attachment #2: udevd-noexec-inotify-09.patch --]
[-- Type: text/plain, Size: 12713 bytes --]

diff --git a/klibc/klibc/SYSCALLS.def b/klibc/klibc/SYSCALLS.def
--- a/klibc/klibc/SYSCALLS.def
+++ b/klibc/klibc/SYSCALLS.def
@@ -114,6 +114,9 @@ int lchown32,lchown::lchown(const char *
 int getcwd::__getcwd(char *, size_t)
 <?> int utime(const char *, const struct utimbuf *)
 <?> int utimes(const char *, const struct timeval *)
+<?> int inotify_init(void)
+<?> int inotify_add_watch(int, const char *, __u32)
+<?> int inotify_rm_watch(int, __u32)
 
 ;
 ; I/O operations
diff --git a/udev_libc_wrapper.h b/udev_libc_wrapper.h
--- a/udev_libc_wrapper.h
+++ b/udev_libc_wrapper.h
@@ -22,6 +22,80 @@
 #ifndef _UDEV_LIBC_WRAPPER_H_
 #define _UDEV_LIBC_WRAPPER_H_
 
+#include <string.h>
+#include <unistd.h>
+#include <linux/types.h>
+#include <sys/syscall.h>
+
+/* needed until Inotify! reaches libc */
+#ifndef __NR_inotify_init
+#if defined(__i386__)
+# define __NR_inotify_init	291
+# define __NR_inotify_add_watch	292
+# define __NR_inotify_rm_watch	293
+#elif defined(__x86_64__)
+# define __NR_inotify_init	253
+# define __NR_inotify_add_watch	254
+# define __NR_inotify_rm_watch	255
+#elif defined(__powerpc__) || defined(__powerpc64__)
+# define __NR_inotify_init	275
+# define __NR_inotify_add_watch	276
+# define __NR_inotify_rm_watch	277
+#elif defined (__ia64__)
+# define __NR_inotify_init	1277
+# define __NR_inotify_add_watch	1278
+# define __NR_inotify_rm_watch	1279
+#elif defined (__s390__)
+# define __NR_inotify_init	284
+# define __NR_inotify_add_watch	285
+# define __NR_inotify_rm_watch	286
+#elif defined (__alpha__)
+# define __NR_inotify_init	444
+# define __NR_inotify_add_watch	445
+# define __NR_inotify_rm_watch	446
+#elif defined (__sparc__) || defined (__sparc64__)
+# define __NR_inotify_init	151
+# define __NR_inotify_add_watch	152
+# define __NR_inotify_rm_watch	156
+#elif defined (__arm__)
+# define __NR_inotify_init	316
+# define __NR_inotify_add_watch	317
+# define __NR_inotify_rm_watch	318
+#elif defined (__sh__)
+# define __NR_inotify_init	290
+# define __NR_inotify_add_watch	291
+# define __NR_inotify_rm_watch	292
+#else
+# error "Unsupported architecture!"
+#endif
+#endif /* __NR_inotify_init */
+
+#ifdef __KLIBC__
+static inline _syscall0(int, inotify_init);
+static inline _syscall3(int, inotify_add_watch, int, fd, const char*, name, __u32, mask);
+#else
+static inline int inotify_init(void)
+{
+	return syscall(__NR_inotify_init);
+}
+
+static inline int inotify_add_watch(int fd, const char *name, __u32 mask)
+{
+	return syscall(__NR_inotify_add_watch, fd, name, mask);
+}
+#endif
+
+/* needed until it reaches libc */
+#ifndef IN_MODIFY
+#define IN_MODIFY		0x00000002	/* File was modified */
+#define IN_MOVED_FROM		0x00000040	/* File was moved from X */
+#define IN_MOVED_TO		0x00000080	/* File was moved to Y */
+#define IN_CREATE		0x00000100	/* Subfile was created */
+#define IN_DELETE		0x00000200	/* Subfile was deleted */
+#define IN_MOVE			(IN_MOVED_FROM | IN_MOVED_TO) /* moves */
+#endif
+
+/* needed for our signal handlers to work */
 #undef asmlinkage
 #ifdef __i386__
 #define asmlinkage	__attribute__((regparm(0)))
@@ -29,6 +103,7 @@
 #define asmlinkage
 #endif
 
+/* headers are broken on some lazy platforms */
 #ifndef __FD_SET
 #define __FD_SET(d, set) ((set)->fds_bits[__FDELT(d)] |= __FDMASK(d))
 #endif
@@ -42,12 +117,11 @@
 #define __FD_ZERO(set) ((void) memset ((void*) (set), 0, sizeof (fd_set)))
 #endif
 
+/* missing in some lazy distros */
 #ifndef NETLINK_KOBJECT_UEVENT
 #define NETLINK_KOBJECT_UEVENT 15
 #endif
 
-#include <string.h>
-
 #ifdef __KLIBC__
 static inline int clearenv(void)
 {
diff --git a/udevcontrol.c b/udevcontrol.c
--- a/udevcontrol.c
+++ b/udevcontrol.c
@@ -89,6 +89,8 @@ int main(int argc, char *argv[], char *e
 			usend_msg.type = UDEVD_STOP_EXEC_QUEUE;
 		else if (!strcmp(arg, "start_exec_queue"))
 			usend_msg.type = UDEVD_START_EXEC_QUEUE;
+		else if (!strcmp(arg, "reload_rules"))
+			usend_msg.type = UDEVD_RELOAD_RULES;
 		else if (!strncmp(arg, "log_priority=", strlen("log_priority="))) {
 			intval = (int *) usend_msg.envbuf;
 			val = &arg[strlen("log_priority=")];
@@ -106,6 +108,7 @@ int main(int argc, char *argv[], char *e
 				"  log_priority=<level> set the udev log level for the daemon\n"
 				"  stop_exec_queue      keep udevd from executing events, queue only\n"
 				"  start_exec_queue     execute events, flush queue\n"
+				"  reload_rules         reloads the rules files\n"
 				"  max_childs=<N>       maximum number of childs running at the same time\n"
 				"  --help               print this help text\n\n");
 			exit(0);
diff --git a/udevd.c b/udevd.c
--- a/udevd.c
+++ b/udevd.c
@@ -30,6 +30,7 @@
 #include <ctype.h>
 #include <dirent.h>
 #include <fcntl.h>
+#include <syslog.h>
 #include <sys/select.h>
 #include <sys/wait.h>
 #include <sys/time.h>
@@ -38,6 +39,7 @@
 #include <sys/un.h>
 #include <sys/sysinfo.h>
 #include <sys/stat.h>
+#include <sys/ioctl.h>
 #include <linux/types.h>
 #include <linux/netlink.h>
 
@@ -45,13 +47,16 @@
 #include "udev_libc_wrapper.h"
 #include "udev.h"
 #include "udev_version.h"
+#include "udev_rules.h"
 #include "udev_utils.h"
 #include "udevd.h"
 #include "logging.h"
 
 /* global variables*/
+struct udev_rules rules;
 static int udevd_sock;
 static int uevent_netlink_sock;
+static int inotify_fd;
 static pid_t sid;
 
 static int pipefds[2] = {-1, -1};
@@ -59,6 +64,7 @@ static volatile int sigchilds_waiting;
 static volatile int run_msg_q;
 static volatile int sig_flag;
 static volatile int udev_exit;
+static volatile int reload_config;
 static int init_phase = 1;
 static int run_exec_q;
 static int stop_exec_q;
@@ -72,12 +78,13 @@ static void msg_queue_manager(void);
 static void user_sighandler(void);
 static void reap_sigchilds(void);
 
-static char *udev_bin;
 static unsigned long long expected_seqnum;
 static int event_timeout;
 static int max_childs;
 static int max_childs_running;
 
+static char log[32];
+
 
 #ifdef USE_LOG
 void log_message (int priority, const char *format, ...)
@@ -164,10 +171,59 @@ static void msg_queue_insert(struct ueve
 	return;
 }
 
+static void asmlinkage udev_event_sig_handler(int signum)
+{
+	if (signum == SIGALRM)
+		exit(1);
+}
+
+static int udev_event_process(struct uevent_msg *msg)
+{
+	struct sigaction act;
+	struct udevice udev;
+	struct name_entry *name_loop;
+	int i;
+	int retval;
+
+	logging_init("udevd-event");
+
+	/* set signal handlers */
+	memset(&act, 0x00, sizeof(act));
+	act.sa_handler = (void (*)(int)) udev_event_sig_handler;
+	sigemptyset (&act.sa_mask);
+	act.sa_flags = 0;
+	sigaction(SIGALRM, &act, NULL);
+
+	/* trigger timeout to prevent hanging processes */
+	alarm(UDEV_ALARM_TIMEOUT);
+
+	/* reconstruct env from message */
+	for (i = 0; msg->envp[i]; i++)
+		putenv(msg->envp[i]);
+
+	udev_init_device(&udev, msg->devpath, msg->subsystem, msg->action);
+	retval = udev_process_event(&rules, &udev);
+
+	/* run programs collected by RUN-key*/
+	if (!retval) {
+		list_for_each_entry(name_loop, &udev.run_list, node) {
+			info("RUN key executes '%s'", name_loop->name);
+			if (strncmp(name_loop->name, "socket:", strlen("socket:")) == 0)
+				pass_env_to_socket(&name_loop->name[strlen("socket:")], msg->devpath, msg->action);
+			else
+				run_program(name_loop->name, udev.subsystem, NULL, 0, NULL, (udev_log_priority >= LOG_DEBUG));
+		}
+	}
+
+	udev_cleanup_device(&udev);
+	logging_close();
+
+	return 0;
+}
+
 /* forks event and removes event from run queue when finished */
 static void udev_event_fork(struct uevent_msg *msg)
 {
-	char *const argv[] = { "udev", msg->subsystem, NULL };
 	pid_t pid;
 	struct sysinfo info;
 
@@ -180,9 +236,9 @@ static void udev_event_fork(struct ueven
 		close(udevd_sock);
 		logging_close();
 		setpriority(PRIO_PROCESS, 0, UDEV_PRIORITY);
-		execve(udev_bin, argv, msg->envp);
-		err("exec of child failed");
-		_exit(1);
+
+		udev_event_process(msg);
+		exit(0);
 	case -1:
 		err("fork of child failed");
 		msg_queue_delete(msg);
@@ -441,7 +497,7 @@ recheck:
 	msg_dump_queue();
 
 	/* set timeout for remaining queued events */
-	if (list_empty(&msg_list) == 0) {
+	if (!list_empty(&msg_list)) {
 		struct itimerval itv = {{0, 0}, {timeout - msg_age, 0}};
 		dbg("next event expires in %li seconds", timeout - msg_age);
 		setitimer(ITIMER_REAL, &itv, NULL);
@@ -571,12 +627,19 @@ static struct uevent_msg *get_udevd_msg(
 		intval = (int *) usend_msg.envbuf;
 		info("udevd message (SET_LOG_PRIORITY) received, udev_log_priority=%i", *intval);
 		udev_log_priority = *intval;
+		sprintf(log, "UDEV_LOG=%i", udev_log_priority);
+		putenv(log);
 		break;
 	case UDEVD_SET_MAX_CHILDS:
 		intval = (int *) usend_msg.envbuf;
 		info("udevd message (UDEVD_SET_MAX_CHILDS) received, max_childs=%i", *intval);
 		max_childs = *intval;
 		break;
+	case UDEVD_RELOAD_RULES:
+		info("udevd message (RELOAD_RULES) received");
+		udev_rules_close(&rules);
+		udev_rules_init(&rules, 0, 1);
+		break;
 	default:
 		dbg("unknown message type");
 	}
@@ -652,6 +715,9 @@ static void asmlinkage sig_handler(int s
 			/* set flag, then write to pipe if needed */
 			sigchilds_waiting = 1;
 			break;
+		case SIGHUP:
+			reload_config = 1;
+			break;
 	}
 
 	/* if pipe is empty, write to pipe to force select to return,
@@ -813,6 +879,7 @@ int main(int argc, char *argv[], char *e
 			stop_exec_q = 1;
 		}
 	}
+
 	if (daemonize) {
 		pid_t pid;
 
@@ -886,9 +953,11 @@ int main(int argc, char *argv[], char *e
 	sigaction(SIGCHLD, &act, NULL);
 	sigaction(SIGHUP, &act, NULL);
 
+	udev_rules_init(&rules, 0, 1);
+
 	if (init_uevent_netlink_sock() < 0) {
 		dbg("uevent socket not available");
- 	}
+	}
 
 	if (init_udevd_socket() < 0) {
 		if (errno == EADDRINUSE)
@@ -899,12 +968,10 @@ int main(int argc, char *argv[], char *e
 		goto exit;
 	}
 
-	/* override of forked udev binary, used for testing */
-	udev_bin = getenv("UDEV_BIN");
-	if (udev_bin != NULL)
-		info("udev binary is set to '%s'", udev_bin);
-	else
-		udev_bin = UDEV_BIN;
+	/* watch config directory */
+	inotify_fd = inotify_init();
+	if (inotify_fd > 0)
+		inotify_add_watch(inotify_fd, udev_rules_filename, IN_CREATE | IN_DELETE | IN_MOVE | IN_MODIFY);
 
 	/* init of expected_seqnum value */
 	value = getenv("UDEVD_EXPECTED_SEQNUM");
@@ -937,18 +1004,28 @@ int main(int argc, char *argv[], char *e
 		max_childs_running = UDEVD_MAX_CHILDS_RUNNING;
 	info("initialize max_childs_running to %u", max_childs_running);
 
+	/* clear environment for forked event processes */
+	clearenv();
+
+	/* export log_priority , as called programs may want to do the same as udev */
+	sprintf(log, "UDEV_LOG=%i", udev_log_priority);
+	putenv(log);
+
+	/* prepare list of file descriptors to watch */
 	FD_ZERO(&readfds);
 	FD_SET(udevd_sock, &readfds);
 	if (uevent_netlink_sock > 0)
 		FD_SET(uevent_netlink_sock, &readfds);
+	if (inotify_fd > 0)
+		FD_SET(inotify_fd, &readfds);
 	FD_SET(pipefds[0], &readfds);
-	maxsockplus = udevd_sock+1;
+	maxsockplus = inotify_fd+1;
+
 	while (!udev_exit) {
 		struct uevent_msg *msg;
 
 		fd_set workreadfds = readfds;
 		retval = select(maxsockplus, &workreadfds, NULL, NULL, NULL);
-
 		if (retval < 0) {
 			if (errno != EINTR)
 				dbg("error in select: %s", strerror(errno));
@@ -982,10 +1059,37 @@ int main(int argc, char *argv[], char *e
 			}
 		}
 
+		/* rules directory inotify message */
+		if (FD_ISSET(inotify_fd, &workreadfds)) {
+			int nbytes;
+
+			/* discard all possible events, we can just reload the config at any event */
+			if ((ioctl(inotify_fd, FIONREAD, &nbytes) == 0) && nbytes) {
+				char *buf;
+
+				reload_config = 1;
+				buf = malloc(nbytes);
+				if (!buf) {
+					err("error getting buffer for inotify, disable watching");
+					close(inotify_fd);
+					inotify_fd = -1;
+				}
+				read(inotify_fd, buf, nbytes);
+				free(buf);
+			}
+		}
+
 		/* received a signal, clear our notification pipe */
 		if (FD_ISSET(pipefds[0], &workreadfds))
 			user_sighandler();
 
+		/* set by inotify or a signal*/
+		if (reload_config) {
+			reload_config = 0;
+			udev_rules_close(&rules);
+			udev_rules_init(&rules, 0, 1);
+		}
+
 		/* forked child have returned */
 		if (sigchilds_waiting) {
 			sigchilds_waiting = 0;
@@ -1011,6 +1115,8 @@ int main(int argc, char *argv[], char *e
 	}
 
 exit:
+	udev_rules_close(&rules);
+
 	if (pipefds[0] > 0)
 		close(pipefds[0]);
 	if (pipefds[1] > 0)
@@ -1018,7 +1124,8 @@ exit:
 
 	if (udevd_sock > 0)
 		close(udevd_sock);
-
+	if (inotify_fd > 0)
+		close(inotify_fd);
 	if (uevent_netlink_sock > 0)
 		close(uevent_netlink_sock);
 
diff --git a/udevd.h b/udevd.h
--- a/udevd.h
+++ b/udevd.h
@@ -54,6 +54,7 @@ enum udevd_msg_type {
 	UDEVD_START_EXEC_QUEUE,
 	UDEVD_SET_LOG_LEVEL,
 	UDEVD_SET_MAX_CHILDS,
+	UDEVD_RELOAD_RULES,
 };
 
 

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

* Re: move udev-rules parsing into the daemon
  2005-07-31  0:42 move udev-rules parsing into the daemon Kay Sievers
                   ` (6 preceding siblings ...)
  2005-08-12  2:49 ` Kay Sievers
@ 2005-08-12 18:04 ` Greg KH
  2005-08-18 19:23 ` Kay Sievers
  8 siblings, 0 replies; 10+ messages in thread
From: Greg KH @ 2005-08-12 18:04 UTC (permalink / raw)
  To: linux-hotplug

On Fri, Aug 12, 2005 at 04:49:36AM +0200, Kay Sievers wrote:
> On Fri, Aug 12, 2005 at 01:06:24AM +0200, Kay Sievers wrote:
> > On Wed, Aug 10, 2005 at 11:13:14PM -0700, Greg KH wrote:
> > > On Tue, Aug 09, 2005 at 04:30:07AM +0200, Kay Sievers wrote:
> > > > Here we go with the Inotify version on top of the current tree.
> > > > I've added some stuff to our libc-wrapper file until the inotify
> > > > headers have reached glibc and we can just add an #include to
> > > > udevd.c for it.
> > > 
> > > Looks good to me.
> > 
> > Here is a version on top of the new 066.
> 
> New version to compile successfully with glibc and klibc on:
>   i386, x86_64, ppc, ppc64, ia64, s390, s390x

I'm happy with this, care to add this to your git tree, so I can add it
to mainline?  Any one else have any objections to this?

thanks,

greg k-h


-------------------------------------------------------
SF.Net email is Sponsored by the Better Software Conference & EXPO
September 19-22, 2005 * San Francisco, CA * Development Lifecycle Practices
Agile & Plan-Driven Development * Managing Projects & Teams * Testing & QA
Security * Process Improvement & Measurement * http://www.sqe.com/bsce5sf
_______________________________________________
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

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

* Re: move udev-rules parsing into the daemon
  2005-07-31  0:42 move udev-rules parsing into the daemon Kay Sievers
                   ` (7 preceding siblings ...)
  2005-08-12 18:04 ` Greg KH
@ 2005-08-18 19:23 ` Kay Sievers
  8 siblings, 0 replies; 10+ messages in thread
From: Kay Sievers @ 2005-08-18 19:23 UTC (permalink / raw)
  To: linux-hotplug

[-- Attachment #1: Type: text/plain, Size: 1076 bytes --]

On Fri, Aug 12, 2005 at 11:04:11AM -0700, Greg KH wrote:
> On Fri, Aug 12, 2005 at 04:49:36AM +0200, Kay Sievers wrote:
> > On Fri, Aug 12, 2005 at 01:06:24AM +0200, Kay Sievers wrote:
> > > On Wed, Aug 10, 2005 at 11:13:14PM -0700, Greg KH wrote:
> > > > On Tue, Aug 09, 2005 at 04:30:07AM +0200, Kay Sievers wrote:
> > > > > Here we go with the Inotify version on top of the current tree.
> > > > > I've added some stuff to our libc-wrapper file until the inotify
> > > > > headers have reached glibc and we can just add an #include to
> > > > > udevd.c for it.
> > > > 
> > > > Looks good to me.
> > > 
> > > Here is a version on top of the new 066.
> > 
> > New version to compile successfully with glibc and klibc on:
> >   i386, x86_64, ppc, ppc64, ia64, s390, s390x
> 
> I'm happy with this, care to add this to your git tree, so I can add it
> to mainline?  Any one else have any objections to this?

Here is a version on top of the current release. We hopefully fixed all
remaining issues with today's version 068 so this can go into mainline
next week.

Thanks,
Kay

[-- Attachment #2: udev-rules-in-daemon-01.patch --]
[-- Type: text/plain, Size: 12788 bytes --]

diff --git a/etc/udev/udev.conf.in b/etc/udev/udev.conf.in
--- a/etc/udev/udev.conf.in
+++ b/etc/udev/udev.conf.in
@@ -9,6 +9,8 @@ udev_db="@udevdir@/.udevdb"
 # The name and location of the udev rules file(s).
 udev_rules="@configdir@/rules.d"
 
-# The syslog(3) priority: "err", "info", or the numerical value.
+# The initial syslog(3) priority: "err", "info", "debug" or its
+# numerical equivalent. For runtime debugging, change the daemons
+# internal state with: "udevcontrol log_priority=<value>".
 udev_log="err"
 
diff --git a/klibc/klibc/SYSCALLS.def b/klibc/klibc/SYSCALLS.def
--- a/klibc/klibc/SYSCALLS.def
+++ b/klibc/klibc/SYSCALLS.def
@@ -114,6 +114,9 @@ int lchown32,lchown::lchown(const char *
 int getcwd::__getcwd(char *, size_t)
 <?> int utime(const char *, const struct utimbuf *)
 <?> int utimes(const char *, const struct timeval *)
+<?> int inotify_init(void)
+<?> int inotify_add_watch(int, const char *, __u32)
+<?> int inotify_rm_watch(int, __u32)
 
 ;
 ; I/O operations
diff --git a/udev_libc_wrapper.h b/udev_libc_wrapper.h
--- a/udev_libc_wrapper.h
+++ b/udev_libc_wrapper.h
@@ -25,6 +25,75 @@
 #include <string.h>
 #include <unistd.h>
 #include <linux/types.h>
+#include <sys/syscall.h>
+
+/* needed until Inotify! reaches libc */
+#ifndef __NR_inotify_init
+#if defined(__i386__)
+# define __NR_inotify_init	291
+# define __NR_inotify_add_watch	292
+# define __NR_inotify_rm_watch	293
+#elif defined(__x86_64__)
+# define __NR_inotify_init	253
+# define __NR_inotify_add_watch	254
+# define __NR_inotify_rm_watch	255
+#elif defined(__powerpc__) || defined(__powerpc64__)
+# define __NR_inotify_init	275
+# define __NR_inotify_add_watch	276
+# define __NR_inotify_rm_watch	277
+#elif defined (__ia64__)
+# define __NR_inotify_init	1277
+# define __NR_inotify_add_watch	1278
+# define __NR_inotify_rm_watch	1279
+#elif defined (__s390__)
+# define __NR_inotify_init	284
+# define __NR_inotify_add_watch	285
+# define __NR_inotify_rm_watch	286
+#elif defined (__alpha__)
+# define __NR_inotify_init	444
+# define __NR_inotify_add_watch	445
+# define __NR_inotify_rm_watch	446
+#elif defined (__sparc__) || defined (__sparc64__)
+# define __NR_inotify_init	151
+# define __NR_inotify_add_watch	152
+# define __NR_inotify_rm_watch	156
+#elif defined (__arm__)
+# define __NR_inotify_init	316
+# define __NR_inotify_add_watch	317
+# define __NR_inotify_rm_watch	318
+#elif defined (__sh__)
+# define __NR_inotify_init	290
+# define __NR_inotify_add_watch	291
+# define __NR_inotify_rm_watch	292
+#else
+# error "Unsupported architecture!"
+#endif
+#endif /* __NR_inotify_init */
+
+#ifdef __KLIBC__
+static inline _syscall0(int, inotify_init);
+static inline _syscall3(int, inotify_add_watch, int, fd, const char*, name, __u32, mask);
+#else
+static inline int inotify_init(void)
+{
+	return syscall(__NR_inotify_init);
+}
+
+static inline int inotify_add_watch(int fd, const char *name, __u32 mask)
+{
+	return syscall(__NR_inotify_add_watch, fd, name, mask);
+}
+#endif
+
+/* needed until it reaches libc */
+#ifndef IN_CREATE
+#define IN_CREATE		0x00000100	/* Subfile was created */
+#define IN_MOVED_FROM		0x00000040	/* File was moved from X */
+#define IN_MOVED_TO		0x00000080	/* File was moved to Y */
+#define IN_DELETE		0x00000200	/* Subfile was deleted */
+#define IN_CLOSE_WRITE		0x00000008	/* Writtable file was closed */
+#define IN_MOVE			(IN_MOVED_FROM | IN_MOVED_TO) /* moves */
+#endif
 
 /* needed for our signal handlers to work */
 #undef asmlinkage
diff --git a/udevcontrol.c b/udevcontrol.c
--- a/udevcontrol.c
+++ b/udevcontrol.c
@@ -89,6 +89,8 @@ int main(int argc, char *argv[], char *e
 			usend_msg.type = UDEVD_STOP_EXEC_QUEUE;
 		else if (!strcmp(arg, "start_exec_queue"))
 			usend_msg.type = UDEVD_START_EXEC_QUEUE;
+		else if (!strcmp(arg, "reload_rules"))
+			usend_msg.type = UDEVD_RELOAD_RULES;
 		else if (!strncmp(arg, "log_priority=", strlen("log_priority="))) {
 			intval = (int *) usend_msg.envbuf;
 			val = &arg[strlen("log_priority=")];
@@ -106,6 +108,7 @@ int main(int argc, char *argv[], char *e
 				"  log_priority=<level> set the udev log level for the daemon\n"
 				"  stop_exec_queue      keep udevd from executing events, queue only\n"
 				"  start_exec_queue     execute events, flush queue\n"
+				"  reload_rules         reloads the rules files\n"
 				"  max_childs=<N>       maximum number of childs running at the same time\n"
 				"  --help               print this help text\n\n");
 			exit(0);
diff --git a/udevd.c b/udevd.c
--- a/udevd.c
+++ b/udevd.c
@@ -39,6 +39,7 @@
 #include <sys/un.h>
 #include <sys/sysinfo.h>
 #include <sys/stat.h>
+#include <sys/ioctl.h>
 #include <linux/types.h>
 #include <linux/netlink.h>
 
@@ -46,13 +47,16 @@
 #include "udev_libc_wrapper.h"
 #include "udev.h"
 #include "udev_version.h"
+#include "udev_rules.h"
 #include "udev_utils.h"
 #include "udevd.h"
 #include "logging.h"
 
 /* global variables*/
+struct udev_rules rules;
 static int udevd_sock;
 static int uevent_netlink_sock;
+static int inotify_fd;
 static pid_t sid;
 
 static int pipefds[2] = {-1, -1};
@@ -60,10 +64,10 @@ static volatile int sigchilds_waiting;
 static volatile int run_msg_q;
 static volatile int sig_flag;
 static volatile int udev_exit;
+static volatile int reload_config;
 static int init_phase = 1;
 static int run_exec_q;
 static int stop_exec_q;
-static char *udev_bin;
 static int event_timeout;
 static int max_childs;
 static int max_childs_running;
@@ -76,7 +80,7 @@ static LIST_HEAD(running_list);
 
 
 #ifdef USE_LOG
-void log_message (int priority, const char *format, ...)
+void log_message(int priority, const char *format, ...)
 {
 	va_list args;
 
@@ -161,10 +165,55 @@ static void msg_queue_insert(struct ueve
 	return;
 }
 
-/* forks event and removes event from run queue when finished */
+static void asmlinkage udev_event_sig_handler(int signum)
+{
+	if (signum == SIGALRM)
+		exit(1);
+}
+
+static int udev_event_process(struct uevent_msg *msg)
+{
+	struct sigaction act;
+	struct udevice udev;
+	struct name_entry *name_loop;
+	int i;
+	int retval;
+
+	/* set signal handlers */
+	memset(&act, 0x00, sizeof(act));
+	act.sa_handler = (void (*)(int)) udev_event_sig_handler;
+	sigemptyset (&act.sa_mask);
+	act.sa_flags = 0;
+	sigaction(SIGALRM, &act, NULL);
+
+	/* trigger timeout to prevent hanging processes */
+	alarm(UDEV_ALARM_TIMEOUT);
+
+	/* reconstruct env from message */
+	for (i = 0; msg->envp[i]; i++)
+		putenv(msg->envp[i]);
+
+	udev_init_device(&udev, msg->devpath, msg->subsystem, msg->action);
+	retval = udev_process_event(&rules, &udev);
+
+	/* run programs collected by RUN-key*/
+	if (!retval) {
+		list_for_each_entry(name_loop, &udev.run_list, node) {
+			if (strncmp(name_loop->name, "socket:", strlen("socket:")) == 0)
+				pass_env_to_socket(&name_loop->name[strlen("socket:")], msg->devpath, msg->action);
+			else
+				run_program(name_loop->name, udev.subsystem, NULL, 0, NULL, (udev_log_priority >= LOG_INFO));
+		}
+	}
+
+	udev_cleanup_device(&udev);
+
+	return 0;
+}
+
+/* runs event and removes event from run queue when finished */
 static void udev_event_run(struct uevent_msg *msg)
 {
-	char *const argv[] = { "udev", msg->subsystem, NULL };
 	pid_t pid;
 	struct sysinfo info;
 
@@ -172,14 +221,20 @@ static void udev_event_run(struct uevent
 	switch (pid) {
 	case 0:
 		/* child */
-		if (uevent_netlink_sock != -1)
+		if (uevent_netlink_sock > 0)
 			close(uevent_netlink_sock);
+		if (inotify_fd > 0)
+			close(inotify_fd);
 		close(udevd_sock);
 		logging_close();
+
+		logging_init("udevd-event");
 		setpriority(PRIO_PROCESS, 0, UDEV_PRIORITY);
-		execve(udev_bin, argv, msg->envp);
-		err("exec of child failed");
-		_exit(1);
+		udev_event_process(msg);
+		info("seq %llu finished", msg->seqnum);
+
+		logging_close();
+		exit(0);
 	case -1:
 		err("fork of child failed");
 		msg_queue_delete(msg);
@@ -547,7 +602,7 @@ static struct uevent_msg *get_udevd_msg(
 	switch (usend_msg.type) {
 	case UDEVD_UEVENT_UDEVSEND:
 	case UDEVD_UEVENT_INITSEND:
-		dbg("udevd event message received");
+		info("udevd event message received");
 		envbuf_size = size - offsetof(struct udevd_msg, envbuf);
 		dbg("envbuf_size=%i", envbuf_size);
 		msg = get_msg_from_envbuf(usend_msg.envbuf, envbuf_size);
@@ -576,6 +631,10 @@ static struct uevent_msg *get_udevd_msg(
 		info("udevd message (UDEVD_SET_MAX_CHILDS) received, max_childs=%i", *intval);
 		max_childs = *intval;
 		break;
+	case UDEVD_RELOAD_RULES:
+		info("udevd message (RELOAD_RULES) received");
+		reload_config = 1;
+		break;
 	default:
 		dbg("unknown message type");
 	}
@@ -651,6 +710,9 @@ static void asmlinkage sig_handler(int s
 			/* set flag, then write to pipe if needed */
 			sigchilds_waiting = 1;
 			break;
+		case SIGHUP:
+			reload_config = 1;
+			break;
 	}
 
 	/* if pipe is empty, write to pipe to force select to return,
@@ -852,17 +914,11 @@ int main(int argc, char *argv[], char *e
 		err("error fcntl on read pipe: %s", strerror(errno));
 		goto exit;
 	}
-	retval = fcntl(pipefds[0], F_SETFD, FD_CLOEXEC);
-	if (retval < 0)
-		err("error fcntl on read pipe: %s", strerror(errno));
 	retval = fcntl(pipefds[1], F_SETFL, O_NONBLOCK);
 	if (retval < 0) {
 		err("error fcntl on write pipe: %s", strerror(errno));
 		goto exit;
 	}
-	retval = fcntl(pipefds[1], F_SETFD, FD_CLOEXEC);
-	if (retval < 0)
-		err("error fcntl on write pipe: %s", strerror(errno));
 
 	/* set signal handlers */
 	memset(&act, 0x00, sizeof(struct sigaction));
@@ -875,24 +931,24 @@ int main(int argc, char *argv[], char *e
 	sigaction(SIGCHLD, &act, NULL);
 	sigaction(SIGHUP, &act, NULL);
 
+	/* parse the rules and keep it in memory */
+	udev_rules_init(&rules, 0, 1);
+
 	if (init_udevd_socket() < 0) {
 		if (errno == EADDRINUSE)
 			dbg("another udevd running, exit");
 		else
 			dbg("error initialising udevd socket: %s", strerror(errno));
-
 		goto exit;
 	}
 
 	if (init_uevent_netlink_sock() < 0)
-		info("uevent socket not available");
+		err("uevent socket not available");
 
-	/* override of forked udev binary, used for testing */
-	udev_bin = getenv("UDEV_BIN");
-	if (udev_bin != NULL)
-		info("udev binary is set to '%s'", udev_bin);
-	else
-		udev_bin = UDEV_BIN;
+	/* watch rules directory */
+	inotify_fd = inotify_init();
+	if (inotify_fd > 0)
+		inotify_add_watch(inotify_fd, udev_rules_filename, IN_CREATE | IN_DELETE | IN_MOVE | IN_CLOSE_WRITE);
 
 	/* init of expected_seqnum value */
 	value = getenv("UDEVD_EXPECTED_SEQNUM");
@@ -925,6 +981,9 @@ int main(int argc, char *argv[], char *e
 		max_childs_running = UDEVD_MAX_CHILDS_RUNNING;
 	info("initialize max_childs_running to %u", max_childs_running);
 
+	/* clear environment for forked event processes */
+	clearenv();
+
 	/* export log_priority , as called programs may want to follow that setting */
 	sprintf(log, "UDEV_LOG=%i", udev_log_priority);
 	putenv(log);
@@ -938,8 +997,10 @@ int main(int argc, char *argv[], char *e
 		FD_SET(udevd_sock, &readfds);
 		if (uevent_netlink_sock > 0)
 			FD_SET(uevent_netlink_sock, &readfds);
+		if (inotify_fd > 0)
+			FD_SET(inotify_fd, &readfds);
 
-		fdcount = select(UDEV_MAX(udevd_sock, uevent_netlink_sock)+1, &readfds, NULL, NULL, NULL);
+		fdcount = select(UDEV_MAX(uevent_netlink_sock, inotify_fd)+1, &readfds, NULL, NULL, NULL);
 		if (fdcount < 0) {
 			if (errno != EINTR)
 				dbg("error in select: %s", strerror(errno));
@@ -986,6 +1047,33 @@ int main(int argc, char *argv[], char *e
 			sig_flag = 0;
 		}
 
+		/* rules directory inotify watch */
+		if (FD_ISSET(inotify_fd, &readfds)) {
+			int nbytes;
+
+			/* discard all possible events, we can just reload the config */
+			if ((ioctl(inotify_fd, FIONREAD, &nbytes) == 0) && nbytes) {
+				char *buf;
+
+				reload_config = 1;
+				buf = malloc(nbytes);
+				if (!buf) {
+					err("error getting buffer for inotify, disable watching");
+					close(inotify_fd);
+					inotify_fd = -1;
+				}
+				read(inotify_fd, buf, nbytes);
+				free(buf);
+			}
+		}
+
+		/* rules changed, set by inotify or a signal*/
+		if (reload_config) {
+			udev_rules_close(&rules);
+			udev_rules_init(&rules, 0, 1);
+			reload_config = 0;
+		}
+
 		/* forked child have returned */
 		if (sigchilds_waiting) {
 			sigchilds_waiting = 0;
@@ -1011,6 +1099,8 @@ int main(int argc, char *argv[], char *e
 	}
 
 exit:
+	udev_rules_close(&rules);
+
 	if (pipefds[0] > 0)
 		close(pipefds[0]);
 	if (pipefds[1] > 0)
@@ -1018,6 +1108,8 @@ exit:
 
 	if (udevd_sock > 0)
 		close(udevd_sock);
+	if (inotify_fd > 0)
+		close(inotify_fd);
 	if (uevent_netlink_sock > 0)
 		close(uevent_netlink_sock);
 
diff --git a/udevd.h b/udevd.h
--- a/udevd.h
+++ b/udevd.h
@@ -54,6 +54,7 @@ enum udevd_msg_type {
 	UDEVD_START_EXEC_QUEUE,
 	UDEVD_SET_LOG_LEVEL,
 	UDEVD_SET_MAX_CHILDS,
+	UDEVD_RELOAD_RULES,
 };
 
 

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

end of thread, other threads:[~2005-08-18 19:23 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-07-31  0:42 move udev-rules parsing into the daemon Kay Sievers
2005-08-02  2:42 ` Kay Sievers
2005-08-06  0:39 ` Greg KH
2005-08-06  3:41 ` Kay Sievers
2005-08-09  2:30 ` Kay Sievers
2005-08-11  6:13 ` Greg KH
2005-08-11 23:06 ` Kay Sievers
2005-08-12  2:49 ` Kay Sievers
2005-08-12 18:04 ` Greg KH
2005-08-18 19:23 ` Kay Sievers

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).