From mboxrd@z Thu Jan 1 00:00:00 1970 From: Kay Sievers Date: Tue, 02 Aug 2005 02:42:44 +0000 Subject: Re: move udev-rules parsing into the daemon Message-Id: <20050802024244.GA22814@vrfy.org> MIME-Version: 1 Content-Type: multipart/mixed; boundary="zhXaljGHf11kAtnf" List-Id: References: <20050731004227.GA26803@vrfy.org> In-Reply-To: <20050731004227.GA26803@vrfy.org> To: linux-hotplug@vger.kernel.org --zhXaljGHf11kAtnf Content-Type: text/plain; charset=us-ascii Content-Disposition: inline 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 --zhXaljGHf11kAtnf Content-Type: text/plain; charset=us-ascii Content-Disposition: inline; filename="udevd-noexec-14.patch" 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, }; --zhXaljGHf11kAtnf-- ------------------------------------------------------- SF.Net email is sponsored by: Discover Easy Linux Migration Strategies from IBM. Find simple to follow Roadmaps, straightforward articles, informative Webcasts and more! Get everything you need to get up to speed, fast. http://ads.osdn.com/?ad_id=7477&alloc_id=16492&op=click _______________________________________________ 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