summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKay Sievers <kay.sievers@suse.de>2005-11-07 02:22:44 +0100
committerKay Sievers <kay.sievers@suse.de>2005-11-07 02:22:44 +0100
commit0b3dfb3d72e1df5f38ecb9669e37e5e77d958343 (patch)
tree6196e26a8f176d6445823ed27e3e5972069923d8
parent1ad45a47cae79a80bb9c9ff287dc46c18b2ddc71 (diff)
udevd: depend on netlink and remove all sequence reorder logic
Netlink will never get out-of-order and we just depend on it from now on. Udevsend messages will have no effect if they contain a sequence number (SEQNUM). Thanks to Bastian Blank <waldi@debian.org>, for the debugging session which identified a bug where the timeouts are not working if inotify was not available. All the timeout handling is removed now and this issue should be solved. Signed-off-by: Kay Sievers <kay.sievers@suse.de>
-rw-r--r--Makefile1
-rw-r--r--udev.h2
-rw-r--r--udevd.c185
-rw-r--r--udevd.h9
-rw-r--r--udevsend.c31
5 files changed, 23 insertions, 205 deletions
diff --git a/Makefile b/Makefile
index 8d280acd48..afa649e522 100644
--- a/Makefile
+++ b/Makefile
@@ -270,7 +270,6 @@ udev_version.h:
@echo \#define UDEV_CONFIG_DIR \"$(configdir)\" >> $@
@echo \#define UDEV_CONFIG_FILE \"$(configdir)/udev.conf\" >> $@
@echo \#define UDEV_RULES_FILE \"$(configdir)/rules.d\" >> $@
- @echo \#define UDEV_BIN \"$(sbindir)/udev\" >> $@
@echo \#define UDEVD_BIN \"$(sbindir)/udevd\" >> $@
# man pages
diff --git a/udev.h b/udev.h
index 66edfd66bf..ecc0a44f91 100644
--- a/udev.h
+++ b/udev.h
@@ -36,7 +36,7 @@
#define VALUE_SIZE 128
#define DEFAULT_PARTITIONS_COUNT 15
-#define UDEV_ALARM_TIMEOUT 120
+#define UDEV_ALARM_TIMEOUT 180
struct udev_rules;
diff --git a/udevd.c b/udevd.c
index 64a6f4d002..dcf5781812 100644
--- a/udevd.c
+++ b/udevd.c
@@ -31,16 +31,14 @@
#include <dirent.h>
#include <fcntl.h>
#include <syslog.h>
+#include <time.h>
#include <sys/select.h>
#include <sys/wait.h>
-#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
-#include <sys/sysinfo.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
-#include <linux/types.h>
#include <linux/netlink.h>
#include "list.h"
@@ -61,19 +59,14 @@ static pid_t sid;
static int signal_pipe[2] = {-1, -1};
static volatile int sigchilds_waiting;
-static volatile int run_msg_q;
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 int event_timeout;
static int max_childs;
static int max_childs_running;
-static unsigned long long expected_seqnum;
static char udev_log[32];
-static LIST_HEAD(msg_list);
static LIST_HEAD(exec_list);
static LIST_HEAD(running_list);
@@ -92,14 +85,11 @@ void log_message(int priority, const char *format, ...)
}
#endif
-static void msg_dump_queue(void)
+static void msg_queue_insert(struct uevent_msg *msg)
{
-#ifdef DEBUG
- struct uevent_msg *msg;
-
- list_for_each_entry(msg, &msg_list, node)
- dbg("sequence %llu in queue", msg->seqnum);
-#endif
+ list_add(&msg->node, &exec_list);
+ msg->queue_time = time(NULL);
+ run_exec_q = 1;
}
static void msg_queue_delete(struct uevent_msg *msg)
@@ -108,53 +98,6 @@ static void msg_queue_delete(struct uevent_msg *msg)
free(msg);
}
-/* orders the message in the queue by sequence number */
-static void msg_queue_insert(struct uevent_msg *msg)
-{
- struct uevent_msg *loop_msg;
- struct sysinfo info;
-
- if (msg->seqnum == 0) {
- dbg("no SEQNUM, move straight to the exec queue");
- list_add_tail(&msg->node, &exec_list);
- run_exec_q = 1;
- return;
- }
-
- /* store timestamp of queuing */
- sysinfo(&info);
- msg->queue_time = info.uptime;
-
- /* with the first event we provide a phase of shorter timeout */
- if (init_phase) {
- static long init_time;
-
- if (init_time == 0)
- init_time = info.uptime;
- if (info.uptime - init_time >= UDEVD_INIT_TIME)
- init_phase = 0;
- }
-
- /* sort message by sequence number into list */
- list_for_each_entry_reverse(loop_msg, &msg_list, node) {
- if (loop_msg->seqnum < msg->seqnum)
- break;
-
- if (loop_msg->seqnum == msg->seqnum) {
- dbg("ignoring duplicate message seq %llu", msg->seqnum);
- free(msg);
- return;
- }
- }
- list_add(&msg->node, &loop_msg->node);
- info("seq %llu queued, '%s' '%s'", msg->seqnum, msg->action, msg->devpath);
-
- /* run msg queue manager */
- run_msg_q = 1;
-
- return;
-}
-
static void asmlinkage udev_event_sig_handler(int signum)
{
if (signum == SIGALRM)
@@ -205,7 +148,6 @@ static int udev_event_process(struct uevent_msg *msg)
static void udev_event_run(struct uevent_msg *msg)
{
pid_t pid;
- struct sysinfo info;
pid = fork();
switch (pid) {
@@ -232,9 +174,8 @@ static void udev_event_run(struct uevent_msg *msg)
break;
default:
/* get SIGCHLD in main loop */
- sysinfo(&info);
info("seq %llu forked, pid [%d], '%s' '%s', %ld seconds old",
- msg->seqnum, pid, msg->action, msg->subsystem, info.uptime - msg->queue_time);
+ msg->seqnum, pid, msg->action, msg->subsystem, time(NULL) - msg->queue_time);
msg->pid = pid;
}
}
@@ -436,61 +377,6 @@ static void exec_queue_manager(void)
}
}
-static void msg_move_exec(struct uevent_msg *msg)
-{
- list_move_tail(&msg->node, &exec_list);
- run_exec_q = 1;
- expected_seqnum = msg->seqnum+1;
- dbg("moved seq %llu to exec, next expected is %llu",
- msg->seqnum, expected_seqnum);
-}
-
-/* msg queue management routine handles the timeouts and dispatches the events */
-static void msg_queue_manager(void)
-{
- struct uevent_msg *loop_msg;
- struct uevent_msg *tmp_msg;
- struct sysinfo info;
- long msg_age = 0;
- int timeout = event_timeout;
-
- dbg("msg queue manager, next expected is %llu", expected_seqnum);
-recheck:
- sysinfo(&info);
- list_for_each_entry_safe(loop_msg, tmp_msg, &msg_list, node) {
- /* move event with expected sequence to the exec list */
- if (loop_msg->seqnum == expected_seqnum) {
- msg_move_exec(loop_msg);
- continue;
- }
-
- /* limit timeout during initialization phase */
- if (init_phase) {
- if (timeout > UDEVD_INIT_EVENT_TIMEOUT)
- timeout = UDEVD_INIT_EVENT_TIMEOUT;
- dbg("initialization phase, timeout %i seconds", timeout);
- }
-
- /* move event with expired timeout to the exec list */
- msg_age = info.uptime - loop_msg->queue_time;
- dbg("seq %llu is %li seconds old", loop_msg->seqnum, msg_age);
- if (msg_age >= timeout) {
- msg_move_exec(loop_msg);
- goto recheck;
- } else
- break;
- }
-
- msg_dump_queue();
-
- /* set timeout for remaining queued events */
- if (!list_empty(&msg_list)) {
- struct itimerval itv = {{0, 0}, {timeout - msg_age, 0}};
- info("next event expires in %li seconds", timeout - msg_age);
- setitimer(ITIMER_REAL, &itv, NULL);
- }
-}
-
static struct uevent_msg *get_msg_from_envbuf(const char *buf, int buf_size)
{
int bufpos;
@@ -691,10 +577,6 @@ static void asmlinkage sig_handler(int signum)
case SIGTERM:
udev_exit = 1;
break;
- case SIGALRM:
- /* set flag, then write to pipe if needed */
- run_msg_q = 1;
- break;
case SIGCHLD:
/* set flag, then write to pipe if needed */
sigchilds_waiting = 1;
@@ -712,13 +594,11 @@ static void udev_done(int pid)
{
/* find msg associated with pid and delete it */
struct uevent_msg *msg;
- struct sysinfo info;
list_for_each_entry(msg, &running_list, node) {
if (msg->pid == pid) {
- sysinfo(&info);
if (msg->queue_time)
- info("seq %llu, pid [%d] exit, %ld seconds old", msg->seqnum, msg->pid, info.uptime - msg->queue_time);
+ info("seq %llu, pid [%d] exit, %ld seconds old", msg->seqnum, msg->pid, time(NULL) - msg->queue_time);
else
info("seq 0, pid [%d] exit", msg->pid);
msg_queue_delete(msg);
@@ -818,10 +698,10 @@ int main(int argc, char *argv[], char *envp[])
struct sigaction act;
fd_set readfds;
const char *value;
- int uevent_netlink_active = 0;
int daemonize = 0;
int i;
int rc = 0;
+ int maxfd;
/* redirect std fd's, if the kernel forks us, we don't have them at all */
fd = open("/dev/null", O_RDWR);
@@ -943,7 +823,6 @@ int main(int argc, char *argv[], char *envp[])
act.sa_flags = SA_RESTART;
sigaction(SIGINT, &act, NULL);
sigaction(SIGTERM, &act, NULL);
- sigaction(SIGALRM, &act, NULL);
sigaction(SIGCHLD, &act, NULL);
sigaction(SIGHUP, &act, NULL);
@@ -952,21 +831,6 @@ int main(int argc, char *argv[], char *envp[])
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");
- if (value) {
- expected_seqnum = strtoull(value, NULL, 10);
- info("initialize expected_seqnum to %llu", expected_seqnum);
- }
-
- /* timeout to wait for missing events */
- value = getenv("UDEVD_EVENT_TIMEOUT");
- if (value)
- event_timeout = strtoul(value, NULL, 10);
- else
- event_timeout = UDEVD_EVENT_TIMEOUT;
- info("initialize event_timeout to %u", event_timeout);
-
/* maximum limit of forked childs */
value = getenv("UDEVD_MAX_CHILDS");
if (value)
@@ -990,6 +854,11 @@ int main(int argc, char *argv[], char *envp[])
sprintf(udev_log, "UDEV_LOG=%i", udev_log_priority);
putenv(udev_log);
+ maxfd = udevd_sock;
+ maxfd = UDEV_MAX(maxfd, uevent_netlink_sock);
+ maxfd = UDEV_MAX(maxfd, signal_pipe[READ_END]);
+ maxfd = UDEV_MAX(maxfd, inotify_fd);
+
while (!udev_exit) {
struct uevent_msg *msg;
int fdcount;
@@ -1001,7 +870,7 @@ int main(int argc, char *argv[], char *envp[])
if (inotify_fd > 0)
FD_SET(inotify_fd, &readfds);
- fdcount = select(UDEV_MAX(uevent_netlink_sock, inotify_fd)+1, &readfds, NULL, NULL, NULL);
+ fdcount = select(maxfd+1, &readfds, NULL, NULL, NULL);
if (fdcount < 0) {
if (errno != EINTR)
dbg("error in select: %s", strerror(errno));
@@ -1012,9 +881,8 @@ int main(int argc, char *argv[], char *envp[])
if (FD_ISSET(udevd_sock, &readfds)) {
msg = get_udevd_msg();
if (msg) {
- /* discard kernel messages if netlink is active */
- if (uevent_netlink_active && msg->type == UDEVD_UEVENT_UDEVSEND && msg->seqnum != 0) {
- info("skip uevent_helper message with SEQNUM, netlink is active");
+ if (msg->type == UDEVD_UEVENT_UDEVSEND && msg->seqnum != 0) {
+ info("skip non-kernel message with SEQNUM");
free(msg);
} else
msg_queue_insert(msg);
@@ -1024,14 +892,8 @@ int main(int argc, char *argv[], char *envp[])
/* get kernel netlink message */
if (FD_ISSET(uevent_netlink_sock, &readfds)) {
msg = get_netlink_msg();
- if (msg) {
+ if (msg)
msg_queue_insert(msg);
- /* disable udevsend with first netlink message */
- if (!uevent_netlink_active) {
- info("uevent_nl message received, disable udevsend messages");
- uevent_netlink_active = 1;
- }
- }
}
/* received a signal, clear our notification pipe */
@@ -1068,24 +930,13 @@ int main(int argc, char *argv[], char *envp[])
udev_rules_init(&rules, 1);
}
- /* forked child have returned */
+ /* forked child has returned */
if (sigchilds_waiting) {
sigchilds_waiting = 0;
reap_sigchilds();
}
- if (run_msg_q) {
- run_msg_q = 0;
- msg_queue_manager();
- }
-
if (run_exec_q) {
- /* clean up running_list before calling exec_queue_manager() */
- if (sigchilds_waiting) {
- sigchilds_waiting = 0;
- reap_sigchilds();
- }
-
run_exec_q = 0;
if (!stop_exec_q)
exec_queue_manager();
diff --git a/udevd.h b/udevd.h
index db510ab24a..884c4b0074 100644
--- a/udevd.h
+++ b/udevd.h
@@ -29,13 +29,6 @@
#define UDEVD_PRIORITY -4
#define UDEV_PRIORITY -2
-/* duration of initialization phase with shorter timeout */
-#define UDEVD_INIT_TIME 5
-#define UDEVD_INIT_EVENT_TIMEOUT 2
-
-/* timeout to wait for missing events */
-#define UDEVD_EVENT_TIMEOUT 5
-
/* maximum limit of runnig childs */
#define UDEVD_MAX_CHILDS 64
/* start to throttle forking if maximum number of running childs in our session is reached */
@@ -68,7 +61,7 @@ struct uevent_msg {
enum udevd_msg_type type;
struct list_head node;
pid_t pid;
- long queue_time;
+ time_t queue_time;
char *action;
char *devpath;
char *subsystem;
diff --git a/udevsend.c b/udevsend.c
index 0ba1b58a4b..29d5bc155e 100644
--- a/udevsend.c
+++ b/udevsend.c
@@ -89,27 +89,6 @@ static int start_daemon(void)
return 0;
}
-static void run_udev(const char *subsystem)
-{
- char *const argv[] = { "udev", (char *)subsystem, NULL };
- pid_t pid;
-
- pid = fork();
- switch (pid) {
- case 0:
- /* child */
- execv(UDEV_BIN, argv);
- err("exec of udev child failed");
- _exit(1);
- break;
- case -1:
- err("fork of udev child failed");
- break;
- default:
- waitpid(pid, NULL, 0);
- }
-}
-
int main(int argc, char *argv[], char *envp[])
{
static struct udevd_msg usend_msg;
@@ -132,7 +111,7 @@ int main(int argc, char *argv[], char *envp[])
sock = socket(AF_LOCAL, SOCK_DGRAM, 0);
if (sock == -1) {
err("error getting socket");
- goto fallback;
+ goto exit;
}
memset(&saddr, 0x00, sizeof(struct sockaddr_un));
@@ -192,7 +171,7 @@ int main(int argc, char *argv[], char *envp[])
if (errno != ECONNREFUSED) {
err("error sending message (%s)", strerror(errno));
- goto fallback;
+ goto exit;
}
if (!started_daemon) {
@@ -200,7 +179,7 @@ int main(int argc, char *argv[], char *envp[])
retval = start_daemon();
if (retval) {
dbg("error starting daemon");
- goto fallback;
+ goto exit;
}
dbg("udevd daemon started");
started_daemon = 1;
@@ -210,10 +189,6 @@ int main(int argc, char *argv[], char *envp[])
}
}
-fallback:
- err("unable to connect to event daemon, try to call udev directly");
- run_udev(subsystem);
-
exit:
if (sock != -1)
close(sock);