X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=udevd.c;h=0049e696f1930a6029974b9c9c3ff8ec9ee2792f;hb=021a294c04ad9e96706914765fe83148c287aded;hp=2e6f5793d3747ea57447e966bf8e91c18e70644d;hpb=79721e0a7770b1a5874ef96cbf93a4c6bd19e138;p=elogind.git diff --git a/udevd.c b/udevd.c index 2e6f5793d..0049e696f 100644 --- a/udevd.c +++ b/udevd.c @@ -47,6 +47,7 @@ static int udevsendsock; static int pipefds[2]; +static long startup_time; static unsigned long long expected_seqnum = 0; static volatile int sigchilds_waiting; static volatile int run_msg_q; @@ -64,7 +65,6 @@ static void reap_sigchilds(void); char *udev_bin; #ifdef LOG -unsigned char logname[LOGNAME_SIZE]; void log_message (int level, const char *format, ...) { va_list args; @@ -101,9 +101,14 @@ static void msg_queue_insert(struct hotplug_msg *msg) struct hotplug_msg *loop_msg; struct sysinfo info; - /* sort message by sequence number into list. events - * will tend to come in order, so scan the list backwards - */ + if (msg->seqnum == 0) { + dbg("no SEQNUM, move straight to the exec queue"); + list_add(&msg->list, &exec_list); + run_exec_q = 1; + return; + } + + /* sort message by sequence number into list */ list_for_each_entry_reverse(loop_msg, &msg_list, list) if (loop_msg->seqnum < msg->seqnum) break; @@ -151,34 +156,51 @@ static void udev_run(struct hotplug_msg *msg) } } -/* returns still running task for the same event sequence */ +static int compare_devpath(const char *running, const char *waiting) +{ + int i; + + for (i = 0; i < DEVPATH_SIZE; i++) { + /* identical device event found */ + if (running[i] == '\0' && waiting[i] == '\0') + return 1; + + /* parent device event found */ + if (running[i] == '\0' && waiting[i] == '/') + return 2; + + /* child device event found */ + if (running[i] == '/' && waiting[i] == '\0') + return 3; + + /* no matching event */ + if (running[i] != waiting[i]) + break; + } + + return 0; +} + +/* returns still running task for the same device, its parent or its physical device */ static struct hotplug_msg *running_with_devpath(struct hotplug_msg *msg) { struct hotplug_msg *loop_msg; - int i; + + if (msg->devpath == NULL) + return NULL; list_for_each_entry(loop_msg, &running_list, list) { - if (loop_msg->devpath == NULL || msg->devpath == NULL) + if (loop_msg->devpath == NULL) continue; - /* is a parent or child device event still running */ - for (i = 0; i < DEVPATH_SIZE; i++) { - if (loop_msg->devpath[i] == '\0' || msg->devpath[i] == '\0') - return loop_msg; - - if (loop_msg->devpath[i] != msg->devpath[i]) - break; - } + /* return running parent/child device event */ + if (compare_devpath(loop_msg->devpath, msg->devpath) != 0) + return loop_msg; - /* is the physical device event still running on an add sequence */ + /* return running physical device event */ if (msg->physdevpath && msg->action && strcmp(msg->action, "add") == 0) - for (i = 0; i < DEVPATH_SIZE; i++) { - if (loop_msg->devpath[i] == '\0' || msg->physdevpath[i] == '\0') - return loop_msg; - - if (loop_msg->devpath[i] != msg->physdevpath[i]) - break; - } + if (compare_devpath(loop_msg->devpath, msg->physdevpath) != 0) + return loop_msg; } return NULL; @@ -221,6 +243,8 @@ static void msg_queue_manager(void) struct hotplug_msg *tmp_msg; struct sysinfo info; long msg_age = 0; + static int timeout = EVENT_INIT_TIMEOUT_SEC; + static int init = 1; dbg("msg queue manager, next expected is %llu", expected_seqnum); recheck: @@ -231,11 +255,18 @@ recheck: continue; } + /* see if we are in the initialization phase and wait for the very first events */ + if (init && (info.uptime - startup_time >= INIT_TIME_SEC)) { + init = 0; + timeout = EVENT_TIMEOUT_SEC; + dbg("initialization phase passed, set timeout to %i seconds", EVENT_TIMEOUT_SEC); + } + /* move event with expired timeout to the exec list */ sysinfo(&info); msg_age = info.uptime - loop_msg->queue_time; dbg("seq %llu is %li seconds old", loop_msg->seqnum, msg_age); - if (msg_age > EVENT_TIMEOUT_SEC-1) { + if (msg_age >= timeout) { msg_move_exec(loop_msg); goto recheck; } else { @@ -247,14 +278,14 @@ recheck: /* set timeout for remaining queued events */ if (list_empty(&msg_list) == 0) { - struct itimerval itv = {{0, 0}, {EVENT_TIMEOUT_SEC - msg_age, 0}}; - dbg("next event expires in %li seconds", EVENT_TIMEOUT_SEC - msg_age); + struct itimerval itv = {{0, 0}, {timeout - msg_age, 0}}; + dbg("next event expires in %li seconds", timeout - msg_age); setitimer(ITIMER_REAL, &itv, NULL); } } -/* receive the msg, do some basic sanity checks, and queue it */ -static void handle_udevsend_msg(int sock) +/* receive the udevsend message and do some sanity checks */ +static struct hotplug_msg *get_udevsend_msg(void) { static struct udevsend_msg usend_msg; struct hotplug_msg *msg; @@ -278,33 +309,36 @@ static void handle_udevsend_msg(int sock) smsg.msg_control = cred_msg; smsg.msg_controllen = sizeof(cred_msg); - size = recvmsg(sock, &smsg, 0); + size = recvmsg(udevsendsock, &smsg, 0); if (size < 0) { if (errno != EINTR) - dbg("unable to receive message"); - return; + dbg("unable to receive udevsend message"); + return NULL; } cmsg = CMSG_FIRSTHDR(&smsg); cred = (struct ucred *) CMSG_DATA(cmsg); if (cmsg == NULL || cmsg->cmsg_type != SCM_CREDENTIALS) { dbg("no sender credentials received, message ignored"); - goto exit; + return NULL; } if (cred->uid != 0) { dbg("sender uid=%i, message ignored", cred->uid); - goto exit; + return NULL; } if (strncmp(usend_msg.magic, UDEV_MAGIC, sizeof(UDEV_MAGIC)) != 0 ) { dbg("message magic '%s' doesn't match, ignore it", usend_msg.magic); - goto exit; + return NULL; } envbuf_size = size - offsetof(struct udevsend_msg, envbuf); dbg("envbuf_size=%i", envbuf_size); msg = malloc(sizeof(struct hotplug_msg) + envbuf_size); + if (msg == NULL) + return NULL; + memset(msg, 0x00, sizeof(struct hotplug_msg) + envbuf_size); /* copy environment buffer and reconstruct envp */ @@ -336,19 +370,10 @@ static void handle_udevsend_msg(int sock) if (strncmp(key, "PHYSDEVPATH=", 12) == 0) msg->physdevpath = &key[12]; } - msg->envp[i++] = "MANAGED_EVENT=1"; + msg->envp[i++] = "UDEVD_EVENT=1"; msg->envp[i] = NULL; - /* if no seqnum is given, we move straight to exec queue */ - if (msg->seqnum == 0) { - list_add(&msg->list, &exec_list); - run_exec_q = 1; - } else { - msg_queue_insert(msg); - } - -exit: - return; + return msg; } static void asmlinkage sig_handler(int signum) @@ -430,6 +455,7 @@ static void user_sighandler(void) int main(int argc, char *argv[], char *envp[]) { + struct sysinfo info; int maxsockplus; struct sockaddr_un saddr; socklen_t addrlen; @@ -533,11 +559,17 @@ int main(int argc, char *argv[], char *envp[]) else udev_bin = UDEV_BIN; + /* handle special startup timeout*/ + sysinfo(&info); + startup_time = info.uptime; + FD_ZERO(&readfds); FD_SET(udevsendsock, &readfds); FD_SET(pipefds[0], &readfds); maxsockplus = udevsendsock+1; while (1) { + struct hotplug_msg *msg; + fd_set workreadfds = readfds; retval = select(maxsockplus, &workreadfds, NULL, NULL, NULL); @@ -547,8 +579,11 @@ int main(int argc, char *argv[], char *envp[]) continue; } - if (FD_ISSET(udevsendsock, &workreadfds)) - handle_udevsend_msg(udevsendsock); + if (FD_ISSET(udevsendsock, &workreadfds)) { + msg = get_udevsend_msg(); + if (msg) + msg_queue_insert(msg); + } if (FD_ISSET(pipefds[0], &workreadfds)) user_sighandler();