From mboxrd@z Thu Jan 1 00:00:00 1970 From: Kay Sievers Date: Tue, 19 Oct 2004 03:26:20 +0000 Subject: Re: experimental udevd with builtin udev Message-Id: <20041019032620.GA9106@vrfy.org> MIME-Version: 1 Content-Type: multipart/mixed; boundary="fUYQa+Pmc3FrFX/N" List-Id: References: <20041018232625.GA8419@vrfy.org> In-Reply-To: <20041018232625.GA8419@vrfy.org> To: linux-hotplug@vger.kernel.org --fUYQa+Pmc3FrFX/N Content-Type: text/plain; charset=us-ascii Content-Disposition: inline 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 --fUYQa+Pmc3FrFX/N Content-Type: text/plain; charset=us-ascii Content-Disposition: inline; filename="udevd-new-noexec-02.patch" ===== 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); --fUYQa+Pmc3FrFX/N-- ------------------------------------------------------- This SF.net email is sponsored by: IT Product Guide on ITManagersJournal Use IT products in your business? Tell us what you think of them. Give us Your Opinions, Get Free ThinkGeek Gift Certificates! Click to find out more http://productguide.itmanagersjournal.com/guidepromo.tmpl _______________________________________________ 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