From: Kay Sievers <kay.sievers@vrfy.org>
To: linux-hotplug@vger.kernel.org
Subject: Re: move udev-rules parsing into the daemon
Date: Fri, 12 Aug 2005 02:49:36 +0000 [thread overview]
Message-ID: <20050812024936.GA18656@vrfy.org> (raw)
In-Reply-To: <20050731004227.GA26803@vrfy.org>
[-- 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,
};
next prev parent reply other threads:[~2005-08-12 2:49 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 [this message]
2005-08-12 18:04 ` Greg KH
2005-08-18 19:23 ` Kay Sievers
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=20050812024936.GA18656@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.