X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=udevd.c;h=110d8e7c4d3a3fe90f547f76e252dbba63f0a0e8;hp=f4c986b870813439c0f8e8ce58a6ce34ccf06ea2;hb=cbbde2ba6c19d6515f09a2ed0955eb2808c91198;hpb=3632a3685883d3270145c59d5764de6246547943 diff --git a/udevd.c b/udevd.c index f4c986b87..110d8e7c4 100644 --- a/udevd.c +++ b/udevd.c @@ -48,9 +48,13 @@ #include "udevd.h" #include "logging.h" +#ifndef NETLINK_KOBJECT_UEVENT +#define NETLINK_KOBJECT_UEVENT 15 +#endif + /* global variables*/ static int udevd_sock; -static int uevent_nl_sock; +static int uevent_netlink_sock; static pid_t sid; static int pipefds[2]; @@ -101,7 +105,7 @@ static void msg_dump_queue(void) #endif } -static void run_queue_delete(struct uevent_msg *msg) +static void msg_queue_delete(struct uevent_msg *msg) { list_del(&msg->node); free(msg); @@ -163,7 +167,7 @@ static void msg_queue_insert(struct uevent_msg *msg) } /* forks event and removes event from run queue when finished */ -static void execute_udev(struct uevent_msg *msg) +static void udev_event_fork(struct uevent_msg *msg) { char *const argv[] = { "udev", msg->subsystem, NULL }; pid_t pid; @@ -173,19 +177,17 @@ static void execute_udev(struct uevent_msg *msg) switch (pid) { case 0: /* child */ - if (uevent_nl_sock != -1) - close(uevent_nl_sock); + if (uevent_netlink_sock != -1) + close(uevent_netlink_sock); close(udevd_sock); logging_close(); - setpriority(PRIO_PROCESS, 0, UDEV_PRIORITY); execve(udev_bin, argv, msg->envp); err("exec of child failed"); _exit(1); - break; case -1: err("fork of child failed"); - run_queue_delete(msg); + msg_queue_delete(msg); break; default: /* get SIGCHLD in main loop */ @@ -362,6 +364,9 @@ static void exec_queue_manager(void) struct uevent_msg *tmp_msg; int running; + if (list_empty(&exec_list)) + return; + running = running_processes(); dbg("%d processes runnning on system", running); if (running < 0) @@ -382,7 +387,7 @@ static void exec_queue_manager(void) if (running_with_devpath(loop_msg, max_childs) == 0) { /* move event to run list */ list_move_tail(&loop_msg->node, &running_list); - execute_udev(loop_msg); + udev_event_fork(loop_msg); running++; dbg("moved seq %llu to running list", loop_msg->seqnum); } else @@ -450,6 +455,8 @@ static struct uevent_msg *get_msg_from_envbuf(const char *buf, int buf_size) int bufpos; int i; struct uevent_msg *msg; + int major = 0; + int minor = 0; msg = malloc(sizeof(struct uevent_msg) + buf_size); if (msg == NULL) @@ -472,22 +479,22 @@ static struct uevent_msg *get_msg_from_envbuf(const char *buf, int buf_size) /* remember some keys for further processing */ if (strncmp(key, "ACTION=", 7) == 0) msg->action = &key[7]; - - if (strncmp(key, "DEVPATH=", 8) == 0) + else if (strncmp(key, "DEVPATH=", 8) == 0) msg->devpath = &key[8]; - - if (strncmp(key, "SUBSYSTEM=", 10) == 0) + else if (strncmp(key, "SUBSYSTEM=", 10) == 0) msg->subsystem = &key[10]; - - if (strncmp(key, "SEQNUM=", 7) == 0) + else if (strncmp(key, "SEQNUM=", 7) == 0) msg->seqnum = strtoull(&key[7], NULL, 10); - - if (strncmp(key, "PHYSDEVPATH=", 12) == 0) + else if (strncmp(key, "PHYSDEVPATH=", 12) == 0) msg->physdevpath = &key[12]; - - if (strncmp(key, "TIMEOUT=", 8) == 0) + else if (strncmp(key, "MAJOR=", 6) == 0) + major = strtoull(&key[6], NULL, 10); + else if (strncmp(key, "MINOR=", 6) == 0) + minor = strtoull(&key[6], NULL, 10); + else if (strncmp(key, "TIMEOUT=", 8) == 0) msg->timeout = strtoull(&key[8], NULL, 10); } + msg->devt = makedev(major, minor); msg->envp[i++] = "UDEVD_EVENT=1"; msg->envp[i] = NULL; @@ -506,6 +513,7 @@ static struct uevent_msg *get_udevd_msg(void) struct ucred *cred; char cred_msg[CMSG_SPACE(sizeof(struct ucred))]; int envbuf_size; + int *intval; memset(&usend_msg, 0x00, sizeof(struct udevd_msg)); iov.iov_base = &usend_msg; @@ -541,10 +549,10 @@ static struct uevent_msg *get_udevd_msg(void) return NULL; } -switch (usend_msg.type) { - case UDEVD_UDEVSEND: - case UDEVD_INITSEND: - dbg("udevd event message received"); + switch (usend_msg.type) { + case UDEVD_UEVENT_UDEVSEND: + case UDEVD_UEVENT_INITSEND: + info("udevd event message received"); envbuf_size = size - offsetof(struct udevd_msg, envbuf); dbg("envbuf_size=%i", envbuf_size); msg = get_msg_from_envbuf(usend_msg.envbuf, envbuf_size); @@ -553,14 +561,24 @@ switch (usend_msg.type) { msg->type = usend_msg.type; return msg; case UDEVD_STOP_EXEC_QUEUE: - dbg("udevd message (STOP_EXEC_QUEUE) received"); + info("udevd message (STOP_EXEC_QUEUE) received"); stop_exec_q = 1; break; case UDEVD_START_EXEC_QUEUE: - dbg("udevd message (START_EXEC_QUEUE) received"); + info("udevd message (START_EXEC_QUEUE) received"); stop_exec_q = 0; exec_queue_manager(); break; + case UDEVD_SET_LOG_LEVEL: + intval = (int *) usend_msg.envbuf; + info("udevd message (SET_LOG_PRIORITY) received, udev_log_priority=%i", *intval); + udev_log_priority = *intval; + 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; default: dbg("unknown message type"); } @@ -568,7 +586,7 @@ switch (usend_msg.type) { } /* receive the kernel user event message and do some sanity checks */ -static struct uevent_msg *get_nl_msg(void) +static struct uevent_msg *get_netlink_msg(void) { struct uevent_msg *msg; int bufpos; @@ -576,7 +594,7 @@ static struct uevent_msg *get_nl_msg(void) static char buffer[UEVENT_BUFFER_SIZE + 512]; char *pos; - size = recv(uevent_nl_sock, &buffer, sizeof(buffer), 0); + size = recv(uevent_netlink_sock, &buffer, sizeof(buffer), 0); if (size < 0) { if (errno != EINTR) dbg("unable to receive udevd message"); @@ -586,14 +604,14 @@ static struct uevent_msg *get_nl_msg(void) if ((size_t)size > sizeof(buffer)-1) size = sizeof(buffer)-1; buffer[size] = '\0'; - dbg("uevent_size=%i", size); + dbg("uevent_size=%zi", size); /* start of event payload */ bufpos = strlen(buffer)+1; msg = get_msg_from_envbuf(&buffer[bufpos], size-bufpos); if (msg == NULL) return NULL; - msg->type = UDEVD_NL; + msg->type = UDEVD_UEVENT_NETLINK; /* validate message */ pos = strchr(buffer, '@'); @@ -661,7 +679,7 @@ static void udev_done(int pid) if (msg->pid == pid) { sysinfo(&info); info("seq %llu exit, %ld seconds old", msg->seqnum, info.uptime - msg->queue_time); - run_queue_delete(msg); + msg_queue_delete(msg); /* we want to run the exec queue manager since there may * be events waiting with the devpath of the one that @@ -702,6 +720,7 @@ static void user_sighandler(void) static int init_udevd_socket(void) { struct sockaddr_un saddr; + const int buffersize = 1024 * 1024; socklen_t addrlen; const int feature_on = 1; int retval; @@ -718,6 +737,9 @@ static int init_udevd_socket(void) return -1; } + /* set receive buffersize */ + setsockopt(udevd_sock, SOL_SOCKET, SO_RCVBUF, &buffersize, sizeof(buffersize)); + /* the bind takes care of ensuring only one copy running */ retval = bind(udevd_sock, (struct sockaddr *) &saddr, addrlen); if (retval < 0) { @@ -732,9 +754,10 @@ static int init_udevd_socket(void) return 0; } -static int init_uevent_nl_sock(void) +static int init_uevent_netlink_sock(void) { struct sockaddr_nl snl; + const int buffersize = 1024 * 1024; int retval; memset(&snl, 0x00, sizeof(struct sockaddr_nl)); @@ -742,18 +765,21 @@ static int init_uevent_nl_sock(void) snl.nl_pid = getpid(); snl.nl_groups = 0xffffffff; - uevent_nl_sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT); - if (uevent_nl_sock == -1) { + uevent_netlink_sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT); + if (uevent_netlink_sock == -1) { dbg("error getting socket, %s", strerror(errno)); return -1; } - retval = bind(uevent_nl_sock, (struct sockaddr *) &snl, + /* set receive buffersize */ + setsockopt(uevent_netlink_sock, SOL_SOCKET, SO_RCVBUF, &buffersize, sizeof(buffersize)); + + retval = bind(uevent_netlink_sock, (struct sockaddr *) &snl, sizeof(struct sockaddr_nl)); if (retval < 0) { dbg("bind failed, %s", strerror(errno)); - close(uevent_nl_sock); - uevent_nl_sock = -1; + close(uevent_netlink_sock); + uevent_netlink_sock = -1; return -1; } @@ -768,7 +794,7 @@ int main(int argc, char *argv[], char *envp[]) struct sigaction act; fd_set readfds; const char *value; - int uevent_nl_active = 0; + int uevent_netlink_active = 0; int daemonize = 0; int i; @@ -788,7 +814,7 @@ int main(int argc, char *argv[], char *envp[]) daemonize = 1; } if (strcmp(arg, "--stop-exec-queue") == 0) { - info("will not execute event until START_EXEC_QUEUE is received"); + info("will not execute events until START_EXEC_QUEUE is received"); stop_exec_q = 1; } } @@ -865,7 +891,7 @@ int main(int argc, char *argv[], char *envp[]) sigaction(SIGALRM, &act, NULL); sigaction(SIGCHLD, &act, NULL); - if (init_uevent_nl_sock() < 0) { + if (init_uevent_netlink_sock() < 0) { dbg("uevent socket not available"); } @@ -918,8 +944,8 @@ int main(int argc, char *argv[], char *envp[]) FD_ZERO(&readfds); FD_SET(udevd_sock, &readfds); - if (uevent_nl_sock != -1) - FD_SET(uevent_nl_sock, &readfds); + if (uevent_netlink_sock != -1) + FD_SET(uevent_netlink_sock, &readfds); FD_SET(pipefds[0], &readfds); maxsockplus = udevd_sock+1; while (1) { @@ -938,7 +964,7 @@ int main(int argc, char *argv[], char *envp[]) msg = get_udevd_msg(); if (msg) { /* discard kernel messages if netlink is active */ - if (uevent_nl_active && msg->type == UDEVD_UDEVSEND && msg->seqnum != 0) { + if (uevent_netlink_active && msg->type == UDEVD_UEVENT_UDEVSEND && msg->seqnum != 0) { dbg("skip uevent_helper message, netlink is active"); free(msg); continue; @@ -947,14 +973,14 @@ int main(int argc, char *argv[], char *envp[]) } } - if (FD_ISSET(uevent_nl_sock, &workreadfds)) { - msg = get_nl_msg(); + if (FD_ISSET(uevent_netlink_sock, &workreadfds)) { + msg = get_netlink_msg(); if (msg) { msg_queue_insert(msg); /* disable udevsend with first netlink message */ - if (!uevent_nl_active) { + if (!uevent_netlink_active) { info("uevent_nl message received, disable udevsend messages"); - uevent_nl_active = 1; + uevent_netlink_active = 1; } } }