linux-hotplug.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* experimental udevd with builtin udev
@ 2004-10-18 23:26 Kay Sievers
  2004-10-19  3:26 ` Kay Sievers
  0 siblings, 1 reply; 2+ messages in thread
From: Kay Sievers @ 2004-10-18 23:26 UTC (permalink / raw)
  To: linux-hotplug

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

Here is an experiment to build udev into udevd instead of loading the
binary from disk. It still forks a child, but the child only handles node
creation/removal and dev.d/ execution.

The rules are only parsed once on startup of udevd. The parsed config is
available to the child, cause we don't exec() anything, we just continue
the execution in the child.

If /dev is on tmpfs, no disk activity will happen on an udev event!

Changes to rules only apply on restart of udevd.

Don't install it! This is highly experimental and may render you system
unusable. It can be easily tested by building it, killing the running
udevd and start the copy in the tree with ./udevd. This copy will listen
to the socket and handle all udev events from udevsend.

The log looks like this:

  udevd[11974]: main: version 039
  udevd[11974]: get_dirs: sysfs_path='/sys'
  udevd[11974]: parse_config_file: reading '/etc/udev/udev.conf' as config file
  udevd[11974]: namedev_parse_rules: reading '/etc/udev/rules.d/50-udev.rules' as rules file
  udevd[11974]: namedev_parse_permissions: reading '/etc/udev/permissions.d/50-udev.permissions' as permissions file
  ...
  kernel: usb 3-2: USB disconnect, address 9
  udevd(event)[11977]: removing device node '/dev/input/mouse2'
  udevd(event)[11979]: removing device node '/dev/input/event3'
  ...
  kernel: usb 3-2: new low speed USB device using address 10
  kernel: input: USB HID v1.10 Mouse [Logitech USB-PS/2 Optical Mouse] on usb-0000:00:1d.1-2
  udevd(event)[11989]: configured rule in '/etc/udev/rules.d/50-udev.rules' at line 24 applied, 'mouse2' becomes 'input/%k'
  udevd(event)[11989]: creating device node '/dev/input/mouse2'
  udevd(event)[11996]: configured rule in '/etc/udev/rules.d/50-udev.rules' at line 25 applied, 'event3' becomes 'input/%k'
  udevd(event)[11996]: creating device node '/dev/input/event3'
  ...

What do you think?

Kay

[-- Attachment #2: udevd-new-noexec-01.patch --]
[-- Type: text/plain, Size: 11235 bytes --]

===== Makefile 1.195 vs edited =====
--- 1.195/Makefile	2004-10-16 00:08:07 +02:00
+++ edited/Makefile	2004-10-19 00:51:02 +02:00
@@ -216,6 +216,7 @@ OBJS =	udev_lib.o	\
 	namedev.o	\
 	namedev_parse.o	\
 	dev_d.o		\
+	udevstart.o		\
 	$(SYSFS)	\
 	$(TDB)
 
@@ -283,7 +284,7 @@ $(STARTER).o: $(GEN_HEADERS) $(HOST_PROG
 $(WAIT).o: $(GEN_HEADERS) $(HOST_PROGS)
 
 $(ROOT): $(LIBC) $(ROOT).o $(STARTER).o $(OBJS) $(HEADERS) $(GEN_MANPAGES)
-	$(QUIET) $(LD) $(LDFLAGS) -o $@ $(CRT0) udev.o udevstart.o $(OBJS) $(LIB_OBJS) $(ARCH_LIB_OBJS)
+	$(QUIET) $(LD) $(LDFLAGS) -o $@ $(CRT0) udev.o $(OBJS) $(LIB_OBJS) $(ARCH_LIB_OBJS)
 	$(QUIET) $(STRIPCMD) $@
 
 $(TESTER): $(LIBC) $(TESTER).o $(OBJS) $(HEADERS)
@@ -295,7 +296,7 @@ $(INFO): $(LIBC) $(INFO).o $(OBJS) $(HEA
 	$(QUIET) $(STRIPCMD) $@
 
 $(DAEMON): $(LIBC) $(DAEMON).o $(OBJS) udevd.h
-	$(QUIET) $(LD) $(LDFLAGS) -o $@ $(CRT0) udevd.o udev_lib.o $(KLIBC_FIXUP) $(LIB_OBJS) $(ARCH_LIB_OBJS)
+	$(QUIET) $(LD) $(LDFLAGS) -o $@ $(CRT0) udevd.o $(OBJS) $(KLIBC_FIXUP) $(LIB_OBJS) $(ARCH_LIB_OBJS)
 	$(QUIET) $(STRIPCMD) $@
 
 $(SENDER): $(LIBC) $(SENDER).o $(OBJS) udevd.h
===== udevd.c 1.42 vs edited =====
--- 1.42/udevd.c	2004-10-19 00:14:20 +02:00
+++ edited/udevd.c	2004-10-19 01:01:52 +02:00
@@ -37,16 +37,26 @@
 #include <sys/sysinfo.h>
 #include <sys/stat.h>
 
+#include "libsysfs/sysfs/libsysfs.h"
 #include "list.h"
+#include "logging.h"
 #include "udev.h"
 #include "udev_lib.h"
 #include "udev_version.h"
 #include "udevd.h"
-#include "logging.h"
+#include "namedev.h"
+#include "udevdb.h"
+
+/* timeout flag for udevdb */
+extern sig_atomic_t gotalarm;
+
+/* global variables */
+char **main_argv;
+char **main_envp;
 
 static int pipefds[2];
 static unsigned long long expected_seqnum = 0;
-static volatile int children_waiting;
+static volatile int childs_waiting;
 static volatile int run_msg_q;
 static volatile int sig_flag;
 static int run_exec_q;
@@ -58,7 +68,7 @@ static LIST_HEAD(running_list);
 static void exec_queue_manager(void);
 static void msg_queue_manager(void);
 static void user_sighandler(void);
-static void reap_kids(void);
+static void reap_childs(void);
 char *udev_bin;
 
 #ifdef LOG
@@ -129,33 +139,118 @@ static void msg_queue_insert(struct hotp
 	return ;
 }
 
+static void asmlinkage udev_sig_handler(int signum)
+{
+	switch (signum) {
+		case SIGALRM:
+			gotalarm = 1;
+			info("error: timeout reached, event probably not handled correctly");
+			break;
+		case SIGINT:
+		case SIGTERM:
+			udevdb_exit();
+			exit(20 + signum);
+		default:
+			dbg("unhandled signal %d", signum);
+	}
+}
+
+static int subsystem_without_dev(const char *subsystem)
+{
+	char *subsystem_blacklist[] = {
+		"scsi_host",
+		"scsi_device",
+		"usb_host",
+		"pci_bus",
+		"pcmcia_socket",
+		"bluetooth",
+		"i2c-adapter",
+		"pci_bus",
+		"ieee1394",
+		"ieee1394_host",
+		"ieee1394_node",
+		NULL
+	};
+	char **subsys;
+
+	for (subsys = subsystem_blacklist; *subsys != NULL; subsys++) {
+		if (strcmp(subsystem, *subsys) == 0)
+			return 1;
+	}
+
+	return 0;
+}
+
 /* forks event and removes event from run queue when finished */
 static void udev_run(struct hotplug_msg *msg)
 {
+	char path[SYSFS_PATH_MAX];
+	struct sysfs_class_device *class_dev;
 	pid_t pid;
-	char action[ACTION_SIZE];
-	char devpath[DEVPATH_SIZE];
-	char seqnum[SEQNUM_SIZE];
-	char *env[] = { action, devpath, seqnum, NULL };
-
-	snprintf(action, ACTION_SIZE-1, "ACTION=%s", msg->action);
-	action[ACTION_SIZE-1] = '\0';
-	snprintf(devpath, DEVPATH_SIZE-1, "DEVPATH=%s", msg->devpath);
-	devpath[DEVPATH_SIZE-1] = '\0';
-	sprintf(seqnum, "SEQNUM=%llu", msg->seqnum);
+	struct sigaction act;
+	int retval = 0;
+	struct udevice udev;
 
 	pid = fork();
 	switch (pid) {
 	case 0:
-		/* child */
-		execle(udev_bin, "udev", msg->subsystem, NULL, env);
-		dbg("exec of child failed");
-		_exit(1);
-		break;
+		/* child reopens log for new name[pid] */
+		logging_close();
+		logging_init("udevd(event)");
+
+		/* set signal handlers */
+		act.sa_handler = (void (*) (int))udev_sig_handler;
+		sigemptyset (&act.sa_mask);
+		/* alarm must not restart syscalls*/
+		sigaction(SIGALRM, &act, NULL);
+		sigaction(SIGINT, &act, NULL);
+		sigaction(SIGTERM, &act, NULL);
+
+		/* trigger timout to interrupt blocking syscalls */
+		alarm(ALARM_TIMEOUT);
+
+		/* we only care about class block devices */
+		if (strstr(msg->devpath, "class") || strstr(msg->devpath, "block")) {
+			/* skip blacklisted subsystems */
+			if (subsystem_without_dev(msg->subsystem)) {
+				dbg("don't care about '%s' devices", msg->subsystem);
+				goto exit;
+			};
+
+			/* initialize udev database */
+			if (udevdb_init(UDEVDB_DEFAULT) != 0)
+				info("error: unable to initialize database, continuing without database");
+
+			udev_set_values(&udev, msg->devpath, msg->subsystem);
+			if (strcmp(msg->action, "add") == 0) {
+				dbg("udev add");
+
+				snprintf(path, SYSFS_PATH_MAX, "%s%s", sysfs_path, udev.devpath);
+				class_dev = sysfs_open_class_device_path(path);
+				if (class_dev == NULL) {
+					dbg ("sysfs_open_class_device_path failed");
+					break;
+				}
+				dbg("opened class_dev->name='%s'", class_dev->name);
+
+				retval = udev_add_device(&udev, class_dev);
+				dev_d_execute(&udev);
+
+			} else if (strcmp(msg->action, "remove") == 0) {
+				dbg("udev remove");
+				retval = udev_remove_device(&udev);
+				dev_d_execute(&udev);
+			}
+			udevdb_exit();
+		}
+
+exit:
+		logging_close();
+		exit(retval);
 	case -1:
 		dbg("fork of child failed");
 		run_queue_delete(msg);
-		/* note: we never managed to run, so we had no impact on 
+		/* note: we never managed to run, so we had no impact on
 		 * running_with_devpath(), so don't bother setting run_exec_q
 		 */
 		break;
@@ -309,7 +404,7 @@ skip:
 	return;
 }
 
-static void asmlinkage sig_handler(int signum)
+static void asmlinkage udevd_sig_handler(int signum)
 {
 	int rc;
 
@@ -325,7 +420,7 @@ static void asmlinkage sig_handler(int s
 			break;
 		case SIGCHLD:
 			/* set flag, then write to pipe if needed */
-			children_waiting = 1;
+			childs_waiting = 1;
 			goto do_write;
 			break;
 		default:
@@ -366,9 +461,9 @@ static void udev_done(int pid)
 	}
 }
 
-static void reap_kids(void)
+static void reap_childs(void)
 {
-	/* reap all dead children */
+	/* reap all dead childs */
 	while(1) {
 		int pid = waitpid(-1, NULL, WNOHANG);
 		if ((pid == -1) || (pid == 0))
@@ -384,7 +479,7 @@ static void user_sighandler(void)
 {
 	int sig;
 	while(1) {
-		int rc = read(pipefds[0],&sig,sizeof(sig));
+		int rc = read(pipefds[0], &sig, sizeof(sig));
 		if (rc < 0)
 			break;
 
@@ -392,27 +487,31 @@ static void user_sighandler(void)
 	}
 }
 
-
-int main(int argc, char *argv[])
+int main(int argc, char *argv[], char *envp[])
 {
 	int ssock, maxsockplus;
 	struct sockaddr_un saddr;
 	socklen_t addrlen;
 	int retval, fd;
-	const int on = 1;
+	const int feature_on = 1;
 	struct sigaction act;
 	fd_set readfds;
 
+	main_argv = argv;
+	main_envp = envp;
+
 	logging_init("udevd");
 	dbg("version %s", UDEV_VERSION);
 
 	if (getuid() != 0) {
 		dbg("need to be root, exit");
-		exit(1);
+		_exit(1);
 	}
+
 	/* make sure we are at top of dir */
 	chdir("/");
-	umask( umask( 077 ) | 022 );
+	umask(umask(077) | 022);
+
 	/* Set fds to dev/null */
 	fd = open( "/dev/null", O_RDWR );
 	if ( fd < 0 ) {
@@ -424,7 +523,8 @@ int main(int argc, char *argv[])
 	dup2(fd, 2);
 	if (fd > 2) 
 		close(fd);
-	/* Get new session id so stray signals don't come our way. */
+
+	/* become session leader */
 	setsid();
 
 	/* setup signal handler pipe */
@@ -456,9 +556,8 @@ int main(int argc, char *argv[])
 		exit(1);
 	}
 
-	
 	/* set signal handlers */
-	act.sa_handler = (void (*) (int))sig_handler;
+	act.sa_handler = (void (*) (int))udevd_sig_handler;
 	sigemptyset(&act.sa_mask);
 	act.sa_flags = SA_RESTART;
 	sigaction(SIGINT, &act, NULL);
@@ -493,14 +592,11 @@ int main(int argc, char *argv[])
 	}
 
 	/* enable receiving of the sender credentials */
-	setsockopt(ssock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on));
+	setsockopt(ssock, SOL_SOCKET, SO_PASSCRED, &feature_on, sizeof(feature_on));
 
-	/* possible override of udev binary, used for testing */
-	udev_bin = getenv("UDEV_BIN");
-	if (udev_bin != NULL)
-		dbg("udev binary is set to '%s'", udev_bin);
-	else
-		udev_bin = UDEV_BIN;
+	/* read config and rules for the forked udev instance */
+	udev_init_config();
+	namedev_init();
 
 	FD_ZERO(&readfds);
 	FD_SET(ssock, &readfds);
@@ -522,9 +618,9 @@ int main(int argc, char *argv[])
 		if (FD_ISSET(pipefds[0], &workreadfds))
 			user_sighandler();
 
-		if (children_waiting) {
-			children_waiting = 0;
-			reap_kids();
+		if (childs_waiting) {
+			childs_waiting = 0;
+			reap_childs();
 		}
 
 		if (run_msg_q) {
@@ -533,14 +629,10 @@ int main(int argc, char *argv[])
 		}
 
 		if (run_exec_q) {
-			/* this is tricky.  exec_queue_manager() loops over exec_list, and
-			 * calls running_with_devpath(), which loops over running_list. This gives
-			 * O(N*M), which can get *nasty*.  Clean up running_list before
-			 * calling exec_queue_manager().
-			 */
-			if (children_waiting) {
-				children_waiting = 0;
-				reap_kids();
+			 /* clean up running_list before calling exec_queue_manager() */
+			if (childs_waiting) {
+				childs_waiting = 0;
+				reap_childs();
 			}
 
 			run_exec_q = 0;
@@ -550,5 +642,5 @@ int main(int argc, char *argv[])
 exit:
 	close(ssock);
 	logging_close();
-	exit(1);
+	return 1;
 }
===== udevd.h 1.12 vs edited =====
--- 1.12/udevd.h	2004-09-14 11:07:37 +02:00
+++ edited/udevd.h	2004-10-19 00:51:02 +02:00
@@ -26,7 +26,6 @@
 
 #define UDEV_MAGIC			"udevd_" UDEV_VERSION
 #define EVENT_TIMEOUT_SEC		10
-#define UDEVSEND_CONNECT_RETRY		20 /* x 100 millisec */
 #define UDEVD_SOCK_PATH			"udevd"
 
 struct hotplug_msg {
===== udevsend.c 1.33 vs edited =====
--- 1.33/udevsend.c	2004-10-16 22:34:31 +02:00
+++ edited/udevsend.c	2004-10-19 00:51:02 +02:00
@@ -41,6 +41,9 @@
 #include "udevd.h"
 #include "logging.h"
 
+#define WAIT_MAX_SECONDS		3
+#define WAIT_LOOP_PER_SECOND		10
+
 #ifdef LOG
 unsigned char logname[LOGNAME_SIZE];
 void log_message (int level, const char *format, ...)
@@ -117,7 +120,6 @@ int main(int argc, char* argv[])
 	unsigned long long seq;
 	int retval = 1;
 	int loop;
-	struct timespec tspec;
 	int sock = -1;
 	struct sockaddr_un saddr;
 	socklen_t addrlen;
@@ -175,8 +177,8 @@ int main(int argc, char* argv[])
 	strfieldcpy(msg.devpath, devpath);
 	strfieldcpy(msg.subsystem, subsystem);
 
-	/* If we can't send, try to start daemon and resend message */
-	loop = UDEVSEND_CONNECT_RETRY;
+	/* If we can't send, try to start daemon and resend message */;
+	loop = WAIT_MAX_SECONDS * WAIT_LOOP_PER_SECOND;
 	while (loop--) {
 		retval = sendto(sock, &msg, sizeof(struct hotplug_msg), 0,
 				(struct sockaddr *)&saddr, addrlen);
@@ -200,10 +202,8 @@ int main(int argc, char* argv[])
 			dbg("daemon started");
 			started_daemon = 1;
 		} else {
-			dbg("retry to connect %d", UDEVSEND_CONNECT_RETRY - loop);
-			tspec.tv_sec = 0;
-			tspec.tv_nsec = 100000000;  /* 100 millisec */
-			nanosleep(&tspec, NULL);
+			dbg("retry to connect %d", WAIT_MAX_SECONDS * WAIT_LOOP_PER_SECOND - loop);
+			usleep(1000 * 1000 / WAIT_LOOP_PER_SECOND);
 		}
 	}
 

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

* Re: experimental udevd with builtin udev
  2004-10-18 23:26 experimental udevd with builtin udev Kay Sievers
@ 2004-10-19  3:26 ` Kay Sievers
  0 siblings, 0 replies; 2+ messages in thread
From: Kay Sievers @ 2004-10-19  3:26 UTC (permalink / raw)
  To: linux-hotplug

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

On Tue, Oct 19, 2004 at 01:26:25AM +0200, Kay Sievers wrote:
> Here is an experiment to build udev into udevd instead of loading the
> binary from disk. It still forks a child, but the child only handles node
> creation/removal and dev.d/ execution.
> 
> The rules are only parsed once on startup of udevd. The parsed config is
> available to the child, cause we don't exec() anything, we just continue
> the execution in the child.
> 
> If /dev is on tmpfs, no disk activity will happen on an udev event!
> 
> Changes to rules only apply on restart of udevd.
> 
> Don't install it! This is highly experimental and may render you system
> unusable. It can be easily tested by building it, killing the running
> udevd and start the copy in the tree with ./udevd. This copy will listen
> to the socket and handle all udev events from udevsend.
> 
> The log looks like this:
> 
>   udevd[11974]: main: version 039
>   udevd[11974]: get_dirs: sysfs_path='/sys'
>   udevd[11974]: parse_config_file: reading '/etc/udev/udev.conf' as config file
>   udevd[11974]: namedev_parse_rules: reading '/etc/udev/rules.d/50-udev.rules' as rules file
>   udevd[11974]: namedev_parse_permissions: reading '/etc/udev/permissions.d/50-udev.permissions' as permissions file
>   ...
>   kernel: usb 3-2: USB disconnect, address 9
>   udevd(event)[11977]: removing device node '/dev/input/mouse2'
>   udevd(event)[11979]: removing device node '/dev/input/event3'
>   ...
>   kernel: usb 3-2: new low speed USB device using address 10
>   kernel: input: USB HID v1.10 Mouse [Logitech USB-PS/2 Optical Mouse] on usb-0000:00:1d.1-2
>   udevd(event)[11989]: configured rule in '/etc/udev/rules.d/50-udev.rules' at line 24 applied, 'mouse2' becomes 'input/%k'
>   udevd(event)[11989]: creating device node '/dev/input/mouse2'
>   udevd(event)[11996]: configured rule in '/etc/udev/rules.d/50-udev.rules' at line 25 applied, 'event3' becomes 'input/%k'
>   udevd(event)[11996]: creating device node '/dev/input/event3'
>   ...
> 
> What do you think?

Here is the version to apply after the last the sysfs-expose and the
udevd-cleanup patch.

Enough for today, thanks,
Kay

[-- Attachment #2: udevd-new-noexec-02.patch --]
[-- Type: text/plain, Size: 5514 bytes --]

===== Makefile 1.197 vs edited =====
--- 1.197/Makefile	2004-10-19 04:07:38 +02:00
+++ edited/Makefile	2004-10-19 05:05:44 +02:00
@@ -217,6 +217,7 @@ OBJS =	udev_lib.o	\
 	namedev.o	\
 	namedev_parse.o	\
 	dev_d.o		\
+	udevstart.o		\
 	$(SYSFS)	\
 	$(TDB)
 
@@ -285,7 +286,7 @@ $(STARTER).o: $(GEN_HEADERS) $(HOST_PROG
 $(WAIT).o: $(GEN_HEADERS) $(HOST_PROGS)
 
 $(ROOT): $(LIBC) $(ROOT).o $(STARTER).o $(OBJS) $(HEADERS) $(GEN_MANPAGES)
-	$(QUIET) $(LD) $(LDFLAGS) -o $@ $(CRT0) udev.o udevstart.o $(OBJS) $(LIB_OBJS) $(ARCH_LIB_OBJS)
+	$(QUIET) $(LD) $(LDFLAGS) -o $@ $(CRT0) udev.o $(OBJS) $(LIB_OBJS) $(ARCH_LIB_OBJS)
 	$(QUIET) $(STRIPCMD) $@
 
 $(TESTER): $(LIBC) $(TESTER).o $(OBJS) $(HEADERS)
@@ -297,7 +298,7 @@ $(INFO): $(LIBC) $(INFO).o $(OBJS) $(HEA
 	$(QUIET) $(STRIPCMD) $@
 
 $(DAEMON): $(LIBC) $(DAEMON).o $(OBJS) udevd.h
-	$(QUIET) $(LD) $(LDFLAGS) -o $@ $(CRT0) udevd.o udev_lib.o $(KLIBC_FIXUP) $(LIB_OBJS) $(ARCH_LIB_OBJS)
+	$(QUIET) $(LD) $(LDFLAGS) -o $@ $(CRT0) udevd.o $(OBJS) $(KLIBC_FIXUP) $(LIB_OBJS) $(ARCH_LIB_OBJS)
 	$(QUIET) $(STRIPCMD) $@
 
 $(SENDER): $(LIBC) $(SENDER).o $(OBJS) udevd.h
===== udevd.c 1.43 vs edited =====
--- 1.43/udevd.c	2004-10-19 05:02:16 +02:00
+++ edited/udevd.c	2004-10-19 05:20:19 +02:00
@@ -43,6 +43,16 @@
 #include "udev_version.h"
 #include "udevd.h"
 #include "logging.h"
+#include "namedev.h"
+#include "udevdb.h"
+#include "udev_sysfs.h"
+
+/* timeout flag for udevdb */
+extern sig_atomic_t gotalarm;
+
+/* global variables */
+char **main_argv;
+char **main_envp;
 
 static int pipefds[2];
 static unsigned long long expected_seqnum = 0;
@@ -129,29 +139,88 @@ static void msg_queue_insert(struct hotp
 	return ;
 }
 
+static void asmlinkage udev_sig_handler(int signum)
+{
+	switch (signum) {
+		case SIGALRM:
+			gotalarm = 1;
+			info("error: timeout reached, event probably not handled correctly");
+			break;
+		case SIGINT:
+		case SIGTERM:
+			udevdb_exit();
+			exit(20 + signum);
+		default:
+			dbg("unhandled signal %d", signum);
+	}
+}
+
 /* forks event and removes event from run queue when finished */
 static void udev_run(struct hotplug_msg *msg)
 {
+	char path[SYSFS_PATH_MAX];
+	struct sysfs_class_device *class_dev;
 	pid_t pid;
-	char action[ACTION_SIZE];
-	char devpath[DEVPATH_SIZE];
-	char seqnum[SEQNUM_SIZE];
-	char *env[] = { action, devpath, seqnum, NULL };
-
-	snprintf(action, ACTION_SIZE-1, "ACTION=%s", msg->action);
-	action[ACTION_SIZE-1] = '\0';
-	snprintf(devpath, DEVPATH_SIZE-1, "DEVPATH=%s", msg->devpath);
-	devpath[DEVPATH_SIZE-1] = '\0';
-	sprintf(seqnum, "SEQNUM=%llu", msg->seqnum);
+	struct sigaction act;
+	int retval = 0;
+	struct udevice udev;
 
 	pid = fork();
 	switch (pid) {
 	case 0:
-		/* child */
-		execle(udev_bin, "udev", msg->subsystem, NULL, env);
-		dbg("exec of child failed");
-		_exit(1);
-		break;
+		/* child reopens log for new name[pid] */
+		logging_close();
+		logging_init("udevd(event)");
+
+		/* set signal handlers */
+		act.sa_handler = (void (*) (int))udev_sig_handler;
+		sigemptyset (&act.sa_mask);
+		/* alarm must not restart syscalls*/
+		sigaction(SIGALRM, &act, NULL);
+		sigaction(SIGINT, &act, NULL);
+		sigaction(SIGTERM, &act, NULL);
+
+		/* trigger timout to interrupt blocking syscalls */
+		alarm(ALARM_TIMEOUT);
+
+		/* we only care about class block devices */
+		if (strstr(msg->devpath, "class") || strstr(msg->devpath, "block")) {
+			/* skip blacklisted subsystems */
+			udev_set_values(&udev, msg->devpath, msg->subsystem);
+			if (udev.type != 'n' && subsystem_expect_no_dev(msg->subsystem)) {
+				dbg("don't care about '%s' devices", msg->subsystem);
+				goto exit;
+			};
+
+			/* initialize udev database */
+			if (udevdb_init(UDEVDB_DEFAULT) != 0)
+				info("error: unable to initialize database, continuing without database");
+
+			if (strcmp(msg->action, "add") == 0) {
+				dbg("udev add");
+
+				snprintf(path, SYSFS_PATH_MAX, "%s%s", sysfs_path, udev.devpath);
+				class_dev = sysfs_open_class_device_path(path);
+				if (class_dev == NULL) {
+					dbg ("sysfs_open_class_device_path failed");
+					break;
+				}
+				dbg("opened class_dev->name='%s'", class_dev->name);
+
+				retval = udev_add_device(&udev, class_dev);
+				dev_d_execute(&udev);
+
+			} else if (strcmp(msg->action, "remove") == 0) {
+				dbg("udev remove");
+				retval = udev_remove_device(&udev);
+				dev_d_execute(&udev);
+			}
+			udevdb_exit();
+		}
+
+exit:
+		logging_close();
+		exit(retval);
 	case -1:
 		dbg("fork of child failed");
 		run_queue_delete(msg);
@@ -309,7 +378,7 @@ skip:
 	return;
 }
 
-static void asmlinkage sig_handler(int signum)
+static void asmlinkage udevd_sig_handler(int signum)
 {
 	int rc;
 
@@ -458,7 +527,7 @@ int main(int argc, char *argv[], char *e
 	}
 
 	/* set signal handlers */
-	act.sa_handler = (void (*) (int)) sig_handler;
+	act.sa_handler = (void (*) (int)) udevd_sig_handler;
 	sigemptyset(&act.sa_mask);
 	act.sa_flags = SA_RESTART;
 	sigaction(SIGINT, &act, NULL);
@@ -495,12 +564,9 @@ int main(int argc, char *argv[], char *e
 	/* enable receiving of the sender credentials */
 	setsockopt(ssock, SOL_SOCKET, SO_PASSCRED, &feature_on, sizeof(feature_on));
 
-	/* possible override of udev binary, used for testing */
-	udev_bin = getenv("UDEV_BIN");
-	if (udev_bin != NULL)
-		dbg("udev binary is set to '%s'", udev_bin);
-	else
-		udev_bin = UDEV_BIN;
+	/* read config and rules files for the forked udev instances */
+	udev_init_config();
+	namedev_init();
 
 	FD_ZERO(&readfds);
 	FD_SET(ssock, &readfds);

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

end of thread, other threads:[~2004-10-19  3:26 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-10-18 23:26 experimental udevd with builtin udev Kay Sievers
2004-10-19  3:26 ` 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).