X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=udev%2Fudevd.c;h=419c486ddd4fca09a341fb5d551337090c7e95ce;hp=5fb6d5f7345e2fc38425fb4b6b70e0a2cadbb1e5;hb=619b97ff2b9e29c79dedd9aff425c7a11764c300;hpb=047f88bca31f364253fe230a1c2ec7fbc43c7fc3 diff --git a/udev/udevd.c b/udev/udevd.c index 5fb6d5f73..419c486dd 100644 --- a/udev/udevd.c +++ b/udev/udevd.c @@ -1,6 +1,8 @@ /* * Copyright (C) 2004-2008 Kay Sievers * Copyright (C) 2004 Chris Friesen + * Copyright (C) 2009 Canonical Ltd. + * Copyright (C) 2009 Scott James Remnant * * 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 @@ -65,10 +67,11 @@ static int debug_trace; static struct udev_rules *rules; static struct udev_ctrl *udev_ctrl; static struct udev_monitor *kernel_monitor; -static volatile int sigchilds_waiting; -static volatile int udev_exit; -static volatile int reload_config; -static volatile int signal_received; +static volatile sig_atomic_t sigchilds_waiting; +static volatile sig_atomic_t udev_exit; +static volatile sig_atomic_t reload_config; +static volatile sig_atomic_t signal_received; +static volatile pid_t settle_pid; static int run_exec_q; static int stop_exec_q; static int max_childs; @@ -169,10 +172,10 @@ static void event_queue_delete(struct udev_event *event) udev_event_unref(event); } -static void asmlinkage event_sig_handler(int signum) +static void event_sig_handler(int signum) { if (signum == SIGALRM) - exit(1); + _exit(1); } static void event_fork(struct udev_event *event) @@ -192,7 +195,6 @@ static void event_fork(struct udev_event *event) switch (pid) { case 0: /* child */ - udev_monitor_unref(kernel_monitor); udev_ctrl_unref(udev_ctrl); logging_close(); logging_init("udevd-event"); @@ -200,7 +202,7 @@ static void event_fork(struct udev_event *event) /* set signal handlers */ memset(&act, 0x00, sizeof(act)); - act.sa_handler = (void (*)(int)) event_sig_handler; + act.sa_handler = event_sig_handler; sigemptyset (&act.sa_mask); act.sa_flags = 0; sigaction(SIGALRM, &act, NULL); @@ -215,9 +217,6 @@ static void event_fork(struct udev_event *event) /* set timeout to prevent hanging processes */ alarm(UDEV_EVENT_TIMEOUT); - /* clear any existing udev watch on the node */ - udev_watch_end(event->udev, event->dev); - /* apply rules, create node, symlinks */ err = udev_event_execute_rules(event, rules); @@ -230,10 +229,13 @@ static void event_fork(struct udev_event *event) udev_event_execute_run(event); /* apply/restore inotify watch */ - if (err == 0 && event->inotify_watch && - strcmp(udev_device_get_action(event->dev), "remove") != 0) - info(event->udev, "device will be watched for changes\n"); + if (err == 0 && event->inotify_watch) { udev_watch_begin(event->udev, event->dev); + udev_device_update_db(event->dev); + } + + /* send processed event back to the kernel netlink socket */ + udev_monitor_send_device(kernel_monitor, event->dev); info(event->udev, "seq %llu exit with %i\n", udev_device_get_seqnum(event->dev), err); logging_close(); @@ -293,7 +295,7 @@ static void event_queue_insert(struct udev_event *event) static int mem_size_mb(void) { - FILE* f; + FILE *f; char buf[4096]; long int memsize = -1; @@ -337,7 +339,7 @@ static int compare_devpath(const char *running, const char *waiting) return 0; } -/* lookup event for identical, parent, child, or physical device */ +/* lookup event for identical, parent, child device */ static int devpath_busy(struct udev_event *event) { struct udev_list_node *loop; @@ -388,19 +390,6 @@ static int devpath_busy(struct udev_event *event) event->delaying_seqnum = udev_device_get_seqnum(loop_event->dev); return 5; } - - /* check physical device event (special case of parent) */ - if (udev_device_get_physdevpath(event->dev) != NULL && - strcmp(udev_device_get_action(event->dev), "add") == 0) - if (compare_devpath(udev_device_get_devpath(loop_event->dev), - udev_device_get_physdevpath(event->dev)) != 0) { - dbg(event->udev, "%llu, physical device event still pending %llu (%s)\n", - udev_device_get_seqnum(event->dev), - udev_device_get_seqnum(loop_event->dev), - udev_device_get_devpath(loop_event->dev)); - event->delaying_seqnum = udev_device_get_seqnum(loop_event->dev); - return 6; - } } return 0; } @@ -516,6 +505,11 @@ static void handle_ctrl_msg(struct udev_ctrl *uctrl) info(udev, "udevd message (SET_MAX_CHILDS) received, max_childs=%i\n", i); max_childs = i; } + + settle_pid = udev_ctrl_get_settle(ctrl_msg); + if (settle_pid > 0) { + info(udev, "udevd message (SETTLE) received\n"); + } udev_ctrl_msg_unref(ctrl_msg); } @@ -539,10 +533,16 @@ static int handle_inotify(struct udev *udev) read(inotify_fd, buf, nbytes); - for (pos = 0, ev = (struct inotify_event *)(buf + pos); pos < nbytes; pos += sizeof(struct inotify_event) + ev->len) { + for (pos = 0; pos < nbytes; pos += sizeof(struct inotify_event) + ev->len) { struct udev_device *dev; - dbg(udev, "inotify event: %x for %d (%s)\n", ev->mask, ev->wd, ev->len ? ev->name : "*"); + ev = (struct inotify_event *)(buf + pos); + if (ev->len) { + dbg(udev, "inotify event: %x for %s\n", ev->mask, ev->name); + reload_config = 1; + continue; + } + dev = udev_watch_lookup(udev, ev->wd); if (dev != NULL) { dbg(udev, "inotify event: %x for %s\n", ev->mask, udev_device_get_devnode(dev)); @@ -562,16 +562,15 @@ static int handle_inotify(struct udev *udev) udev_watch_end(udev, dev); udev_device_unref(dev); - } else { - reload_config = 1; } + } free (buf); return 0; } -static void asmlinkage sig_handler(int signum) +static void sig_handler(int signum) { switch (signum) { case SIGINT: @@ -696,6 +695,34 @@ static void export_initial_seqnum(struct udev *udev) } } +static void startup_log(struct udev *udev) +{ + FILE *f; + char path[UTIL_PATH_SIZE]; + struct stat statbuf; + + f = fopen("/dev/kmsg", "w"); + if (f != NULL) + fprintf(f, "<6>udev: starting version " VERSION "\n"); + + util_strlcpy(path, udev_get_sys_path(udev), sizeof(path)); + util_strlcat(path, "/class/mem/null", sizeof(path)); + if (lstat(path, &statbuf) == 0 && S_ISDIR(statbuf.st_mode)) { + const char *depr_str = + "udev: missing sysfs features; please update the kernel " + "or disable the kernel's CONFIG_SYSFS_DEPRECATED option; " + "udev may fail to work correctly"; + + if (f != NULL) + fprintf(f, "<3>%s\n", depr_str); + err(udev, "%s\n", depr_str); + sleep(3); + } + + if (f != NULL) + fclose(f); +} + int main(int argc, char *argv[]) { struct udev *udev; @@ -801,7 +828,7 @@ int main(int argc, char *argv[]) goto exit; } - kernel_monitor = udev_monitor_new_from_netlink(udev); + kernel_monitor = udev_monitor_new_from_netlink(udev, "kernel"); if (kernel_monitor == NULL || udev_monitor_enable_receiving(kernel_monitor) < 0) { fprintf(stderr, "error initializing netlink socket\n"); err(udev, "error initializing netlink socket\n"); @@ -863,31 +890,11 @@ int main(int argc, char *argv[]) close(fd); } - fd = open("/dev/kmsg", O_WRONLY); - if (fd > 0) { - const char *ver_str = "<6>udev: starting version " VERSION "\n"; - char path[UTIL_PATH_SIZE]; - struct stat statbuf; - - write(fd, ver_str, strlen(ver_str)); - util_strlcpy(path, udev_get_sys_path(udev), sizeof(path)); - util_strlcat(path, "/class/mem/null", sizeof(path)); - if (lstat(path, &statbuf) == 0) { - if (S_ISDIR(statbuf.st_mode)) { - const char *depr_str = - "<6>udev: deprecated sysfs layout; update the kernel or " - "disable CONFIG_SYSFS_DEPRECATED; some udev features will " - "not work correctly\n"; - - write(fd, depr_str, strlen(depr_str)); - } - } - close(fd); - } + startup_log(udev); /* set signal handlers */ memset(&act, 0x00, sizeof(struct sigaction)); - act.sa_handler = (void (*)(int)) sig_handler; + act.sa_handler = sig_handler; sigemptyset(&act.sa_mask); act.sa_flags = SA_RESTART; sigaction(SIGINT, &act, NULL); @@ -1021,6 +1028,11 @@ handle_signals: if (!stop_exec_q) event_queue_manager(udev); } + + if (settle_pid > 0) { + kill(settle_pid, SIGUSR1); + settle_pid = 0; + } } cleanup_queue_dir(udev); rc = 0;