All of lore.kernel.org
 help / color / mirror / Atom feed
From: Kay Sievers <kay.sievers@vrfy.org>
To: linux-hotplug@vger.kernel.org
Subject: Re: move udev-rules parsing into the daemon
Date: Thu, 18 Aug 2005 19:23:27 +0000	[thread overview]
Message-ID: <20050818192327.GA10257@vrfy.org> (raw)
In-Reply-To: <20050731004227.GA26803@vrfy.org>

[-- 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,
 };
 
 

      parent reply	other threads:[~2005-08-18 19:23 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
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 message]

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=20050818192327.GA10257@vrfy.org \
    --to=kay.sievers@vrfy.org \
    --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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.