X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=udev%2Fudevd.c;h=e1ae7eac5459ecaea2fe8cbd5b9f119431557275;hp=a711df53d4785c566da08568a5d04ceffc17ee97;hb=fb762bb928772f1923fef1e342d8ebca9bf7691f;hpb=d59f11e1407ec6fa26e3a6f20b2d404af6978199 diff --git a/udev/udevd.c b/udev/udevd.c index a711df53d..e1ae7eac5 100644 --- a/udev/udevd.c +++ b/udev/udevd.c @@ -1,24 +1,21 @@ /* - * Copyright (C) 2004-2006 Kay Sievers + * Copyright (C) 2004-2008 Kay Sievers * Copyright (C) 2004 Chris Friesen * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation version 2 of the License. + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ -#include "config.h" - #include #include #include @@ -47,15 +44,12 @@ #include "udev.h" #include "udev_rules.h" -#include "udev_selinux.h" #define UDEVD_PRIORITY -4 #define UDEV_PRIORITY -2 /* maximum limit of forked childs */ #define UDEVD_MAX_CHILDS 256 -/* start to throttle forking if maximum number of running childs in our session is reached */ -#define UDEVD_MAX_CHILDS_RUNNING 16 static int debug; @@ -95,7 +89,6 @@ static struct udev_rules rules; static struct udev_ctrl *udev_ctrl; static int uevent_netlink_sock = -1; static int inotify_fd = -1; -static pid_t sid; static int signal_pipe[2] = {-1, -1}; static volatile int sigchilds_waiting; @@ -104,7 +97,6 @@ static volatile int reload_config; static int run_exec_q; static int stop_exec_q; static int max_childs; -static int max_childs_running; static char udev_log_env[32]; static LIST_HEAD(exec_list); @@ -147,7 +139,7 @@ static int udev_event_process(struct udevd_uevent_msg *msg) udevice = udev_device_init(msg->udev); if (udevice == NULL) return -1; - strlcpy(udevice->action, msg->action, sizeof(udevice->action)); + util_strlcpy(udevice->action, msg->action, sizeof(udevice->action)); sysfs_device_set_values(udevice->udev, udevice->dev, msg->devpath, msg->subsystem, msg->driver); udevice->devpath_old = msg->devpath_old; udevice->devt = msg->devt; @@ -174,39 +166,39 @@ enum event_state { static void export_event_state(struct udevd_uevent_msg *msg, enum event_state state) { - char filename[PATH_SIZE]; - char filename_failed[PATH_SIZE]; + char filename[UTIL_PATH_SIZE]; + char filename_failed[UTIL_PATH_SIZE]; size_t start; /* location of queue file */ snprintf(filename, sizeof(filename), "%s/.udev/queue/%llu", udev_get_dev_path(msg->udev), msg->seqnum); /* location of failed file */ - strlcpy(filename_failed, udev_get_dev_path(msg->udev), sizeof(filename_failed)); - strlcat(filename_failed, "/", sizeof(filename_failed)); - start = strlcat(filename_failed, ".udev/failed/", sizeof(filename_failed)); - strlcat(filename_failed, msg->devpath, sizeof(filename_failed)); - path_encode(&filename_failed[start], sizeof(filename_failed) - start); + util_strlcpy(filename_failed, udev_get_dev_path(msg->udev), sizeof(filename_failed)); + util_strlcat(filename_failed, "/", sizeof(filename_failed)); + start = util_strlcat(filename_failed, ".udev/failed/", sizeof(filename_failed)); + util_strlcat(filename_failed, msg->devpath, sizeof(filename_failed)); + util_path_encode(&filename_failed[start], sizeof(filename_failed) - start); switch (state) { case EVENT_QUEUED: unlink(filename_failed); delete_path(msg->udev, filename_failed); create_path(msg->udev, filename); - selinux_setfscreatecon(msg->udev, filename, NULL, S_IFLNK); + udev_selinux_setfscreatecon(msg->udev, filename, S_IFLNK); symlink(msg->devpath, filename); - selinux_resetfscreatecon(msg->udev); + udev_selinux_resetfscreatecon(msg->udev); break; case EVENT_FINISHED: if (msg->devpath_old != NULL) { /* "move" event - rename failed file to current name, do not delete failed */ - char filename_failed_old[PATH_SIZE]; + char filename_failed_old[UTIL_PATH_SIZE]; - strlcpy(filename_failed_old, udev_get_dev_path(msg->udev), sizeof(filename_failed_old)); - strlcat(filename_failed_old, "/", sizeof(filename_failed_old)); - start = strlcat(filename_failed_old, ".udev/failed/", sizeof(filename_failed_old)); - strlcat(filename_failed_old, msg->devpath_old, sizeof(filename_failed_old)); - path_encode(&filename_failed_old[start], sizeof(filename) - start); + util_strlcpy(filename_failed_old, udev_get_dev_path(msg->udev), sizeof(filename_failed_old)); + util_strlcat(filename_failed_old, "/", sizeof(filename_failed_old)); + start = util_strlcat(filename_failed_old, ".udev/failed/", sizeof(filename_failed_old)); + util_strlcat(filename_failed_old, msg->devpath_old, sizeof(filename_failed_old)); + util_path_encode(&filename_failed_old[start], sizeof(filename) - start); if (rename(filename_failed_old, filename_failed) == 0) info(msg->udev, "renamed devpath, moved failed state of '%s' to %s'\n", @@ -285,7 +277,7 @@ static void udev_event_run(struct udevd_uevent_msg *msg) static void msg_queue_insert(struct udevd_uevent_msg *msg) { - char filename[PATH_SIZE]; + char filename[UTIL_PATH_SIZE]; int fd; msg->queue_time = time(NULL); @@ -293,8 +285,8 @@ static void msg_queue_insert(struct udevd_uevent_msg *msg) export_event_state(msg, EVENT_QUEUED); info(msg->udev, "seq %llu queued, '%s' '%s'\n", msg->seqnum, msg->action, msg->subsystem); - strlcpy(filename, udev_get_dev_path(msg->udev), sizeof(filename)); - strlcat(filename, "/.udev/uevent_seqnum", sizeof(filename)); + util_strlcpy(filename, udev_get_dev_path(msg->udev), sizeof(filename)); + util_strlcat(filename, "/.udev/uevent_seqnum", sizeof(filename)); fd = open(filename, O_WRONLY|O_TRUNC|O_CREAT, 0644); if (fd >= 0) { char str[32]; @@ -348,119 +340,11 @@ static int mem_size_mb(void) return memsize; } -static int cpu_count(void) -{ - FILE* f; - char buf[4096]; - int count = 0; - - f = fopen("/proc/stat", "r"); - if (f == NULL) - return -1; - - while (fgets(buf, sizeof(buf), f) != NULL) { - if (strncmp(buf, "cpu", 3) == 0 && isdigit(buf[3])) - count++; - } - - fclose(f); - if (count == 0) - return -1; - return count; -} - -static int running_processes(void) -{ - FILE* f; - char buf[4096]; - int running = -1; - - f = fopen("/proc/stat", "r"); - if (f == NULL) - return -1; - - while (fgets(buf, sizeof(buf), f) != NULL) { - int value; - - if (sscanf(buf, "procs_running %u", &value) == 1) { - running = value; - break; - } - } - - fclose(f); - return running; -} - -/* return the number of process es in our session, count only until limit */ -static int running_processes_in_session(pid_t session, int limit) -{ - DIR *dir; - struct dirent *dent; - int running = 0; - - dir = opendir("/proc"); - if (!dir) - return -1; - - /* read process info from /proc */ - for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) { - int f; - char procdir[64]; - char line[256]; - const char *pos; - char state; - pid_t ppid, pgrp, sess; - int len; - - if (!isdigit(dent->d_name[0])) - continue; - - snprintf(procdir, sizeof(procdir), "/proc/%s/stat", dent->d_name); - procdir[sizeof(procdir)-1] = '\0'; - - f = open(procdir, O_RDONLY); - if (f == -1) - continue; - - len = read(f, line, sizeof(line)-1); - close(f); - - if (len <= 0) - continue; - else - line[len] = '\0'; - - /* skip ugly program name */ - pos = strrchr(line, ')') + 2; - if (pos == NULL) - continue; - - if (sscanf(pos, "%c %d %d %d ", &state, &ppid, &pgrp, &sess) != 4) - continue; - - /* count only processes in our session */ - if (sess != session) - continue; - - /* count only running, no sleeping processes */ - if (state != 'R') - continue; - - running++; - if (limit > 0 && running >= limit) - break; - } - closedir(dir); - - return running; -} - static int compare_devpath(const char *running, const char *waiting) { int i; - for (i = 0; i < PATH_SIZE; i++) { + for (i = 0; i < UTIL_PATH_SIZE; i++) { /* identical device event found */ if (running[i] == '\0' && waiting[i] == '\0') return 1; @@ -524,8 +408,10 @@ static int devpath_busy(struct udevd_uevent_msg *msg, int limit) /* check run queue for still running events */ list_for_each_entry(loop_msg, &running_list, node) { - if (limit && childs_count++ > limit) { - dbg(msg->udev, "%llu, maximum number (%i) of childs reached\n", msg->seqnum, childs_count); + childs_count++; + + if (childs_count++ >= limit) { + info(msg->udev, "%llu, maximum number (%i) of childs reached\n", msg->seqnum, childs_count); return 1; } @@ -565,27 +451,11 @@ static void msg_queue_manager(struct udev *udev) { struct udevd_uevent_msg *loop_msg; struct udevd_uevent_msg *tmp_msg; - int running; if (list_empty(&exec_list)) return; - running = running_processes(); - dbg(udev, "%d processes runnning on system\n", running); - if (running < 0) - running = max_childs_running; - list_for_each_entry_safe(loop_msg, tmp_msg, &exec_list, node) { - /* check running processes in our session and possibly throttle */ - if (running >= max_childs_running) { - running = running_processes_in_session(sid, max_childs_running+10); - dbg(udev, "at least %d processes running in session\n", running); - if (running >= max_childs_running) { - dbg(udev, "delay seq %llu, too many processes already running\n", loop_msg->seqnum); - return; - } - } - /* serialize and wait for parent or child events */ if (devpath_busy(loop_msg, max_childs) != 0) { dbg(udev, "delay seq %llu (%s)\n", loop_msg->seqnum, loop_msg->devpath); @@ -595,7 +465,6 @@ static void msg_queue_manager(struct udev *udev) /* move event to run list */ list_move_tail(&loop_msg->node, &running_list); udev_event_run(loop_msg); - running++; dbg(udev, "moved seq %llu to running list\n", loop_msg->seqnum); } } @@ -735,12 +604,6 @@ static void handle_ctrl_msg(struct udev_ctrl *uctrl) max_childs = i; } - i = udev_ctrl_get_set_max_childs_running(ctrl_msg); - if (i > 0) { - info(udev, "udevd message (SET_MAX_CHILDS_RUNNING) received, max_childs_running=%i\n", i); - max_childs_running = i; - } - udev_ctrl_msg_unref(ctrl_msg); } @@ -885,13 +748,13 @@ static int init_uevent_netlink_sock(struct udev *udev) static void export_initial_seqnum(struct udev *udev) { - char filename[PATH_SIZE]; + char filename[UTIL_PATH_SIZE]; int fd; char seqnum[32]; ssize_t len = 0; - strlcpy(filename, udev_get_sys_path(udev), sizeof(filename)); - strlcat(filename, "/kernel/uevent_seqnum", sizeof(filename)); + util_strlcpy(filename, udev_get_sys_path(udev), sizeof(filename)); + util_strlcat(filename, "/kernel/uevent_seqnum", sizeof(filename)); fd = open(filename, O_RDONLY); if (fd >= 0) { len = read(fd, seqnum, sizeof(seqnum)-1); @@ -901,8 +764,8 @@ static void export_initial_seqnum(struct udev *udev) strcpy(seqnum, "0\n"); len = 3; } - strlcpy(filename, udev_get_dev_path(udev), sizeof(filename)); - strlcat(filename, "/.udev/uevent_seqnum", sizeof(filename)); + util_strlcpy(filename, udev_get_dev_path(udev), sizeof(filename)); + util_strlcat(filename, "/.udev/uevent_seqnum", sizeof(filename)); create_path(udev, filename); fd = open(filename, O_WRONLY|O_TRUNC|O_CREAT, 0644); if (fd >= 0) { @@ -937,8 +800,6 @@ int main(int argc, char *argv[]) logging_init("udevd"); udev_set_log_fn(udev, log_fn); - - selinux_init(udev); dbg(udev, "version %s\n", VERSION); while (1) { @@ -1079,10 +940,7 @@ int main(int argc, char *argv[]) chdir("/"); umask(022); - - /* become session leader */ - sid = setsid(); - dbg(udev, "our session is %d\n", sid); + setsid(); /* OOM_DISABLE == -17 */ fd = open("/proc/self/oom_adj", O_RDWR); @@ -1126,8 +984,8 @@ int main(int argc, char *argv[]) IN_CREATE | IN_DELETE | IN_MOVE | IN_CLOSE_WRITE); /* watch dynamic rules directory */ - strlcpy(filename, udev_get_dev_path(udev), sizeof(filename)); - strlcat(filename, "/.udev/rules.d", sizeof(filename)); + util_strlcpy(filename, udev_get_dev_path(udev), sizeof(filename)); + util_strlcat(filename, "/.udev/rules.d", sizeof(filename)); inotify_add_watch(inotify_fd, filename, IN_CREATE | IN_DELETE | IN_MOVE | IN_CLOSE_WRITE); } @@ -1149,19 +1007,6 @@ int main(int argc, char *argv[]) } info(udev, "initialize max_childs to %u\n", max_childs); - /* start to throttle forking if maximum number of _running_ childs is reached */ - value = getenv("UDEVD_MAX_CHILDS_RUNNING"); - if (value) - max_childs_running = strtoull(value, NULL, 10); - else { - int cpus = cpu_count(); - if (cpus > 0) - max_childs_running = 8 + (8 * cpus); - else - max_childs_running = UDEVD_MAX_CHILDS_RUNNING; - } - info(udev, "initialize max_childs_running to %u\n", max_childs_running); - /* clear environment for forked event processes */ clearenv(); @@ -1256,7 +1101,6 @@ int main(int argc, char *argv[]) exit: udev_rules_cleanup(&rules); sysfs_cleanup(); - selinux_exit(udev); if (signal_pipe[READ_END] >= 0) close(signal_pipe[READ_END]);