X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=udev%2Fudevd.c;h=5ee61d2e23c296c853a453b97729741e973da6f5;hp=419c486ddd4fca09a341fb5d551337090c7e95ce;hb=f503f6b22fa54d1a65156a51d8b3311190c73ae5;hpb=619b97ff2b9e29c79dedd9aff425c7a11764c300 diff --git a/udev/udevd.c b/udev/udevd.c index 419c486dd..5ee61d2e2 100644 --- a/udev/udevd.c +++ b/udev/udevd.c @@ -65,6 +65,7 @@ static void reap_sigchilds(void); static int debug_trace; static struct udev_rules *rules; +static struct udev_queue_export *udev_queue_export; static struct udev_ctrl *udev_ctrl; static struct udev_monitor *kernel_monitor; static volatile sig_atomic_t sigchilds_waiting; @@ -78,12 +79,6 @@ static int max_childs; static int childs; static struct udev_list_node event_list; -enum event_state { - EVENT_QUEUED, - EVENT_FINISHED, - EVENT_FAILED, -}; - static struct udev_event *node_to_event(struct udev_list_node *node) { char *event; @@ -93,80 +88,15 @@ static struct udev_event *node_to_event(struct udev_list_node *node) return (struct udev_event *)event; } -static void export_event_state(struct udev_event *event, enum event_state state) -{ - 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(event->udev), udev_device_get_seqnum(event->dev)); - - /* location of failed file */ - util_strlcpy(filename_failed, udev_get_dev_path(event->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, udev_device_get_devpath(event->dev), sizeof(filename_failed)); - util_path_encode(&filename_failed[start], sizeof(filename_failed) - start); - - switch (state) { - case EVENT_QUEUED: - if(unlink(filename_failed) == 0) - util_delete_path(event->udev, filename_failed); - util_create_path(event->udev, filename); - udev_selinux_setfscreatecon(event->udev, filename, S_IFLNK); - symlink(udev_device_get_devpath(event->dev), filename); - udev_selinux_resetfscreatecon(event->udev); - break; - case EVENT_FINISHED: - if (udev_device_get_devpath_old(event->dev) != NULL) { - /* "move" event - rename failed file to current name, do not delete failed */ - char filename_failed_old[UTIL_PATH_SIZE]; - - util_strlcpy(filename_failed_old, udev_get_dev_path(event->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, udev_device_get_devpath_old(event->dev), sizeof(filename_failed_old)); - util_path_encode(&filename_failed_old[start], sizeof(filename) - start); - - if (rename(filename_failed_old, filename_failed) == 0) - info(event->udev, "renamed devpath, moved failed state of '%s' to %s'\n", - udev_device_get_devpath_old(event->dev), udev_device_get_devpath(event->dev)); - } else { - if (unlink(filename_failed) == 0) - util_delete_path(event->udev, filename_failed); - } - - unlink(filename); - - /* clean up possibly empty queue directory */ - if (udev_list_is_empty(&event_list)) - util_delete_path(event->udev, filename); - break; - case EVENT_FAILED: - /* move failed event to the failed directory */ - util_create_path(event->udev, filename_failed); - rename(filename, filename_failed); - - /* clean up possibly empty queue directory */ - if (udev_list_is_empty(&event_list)) - util_delete_path(event->udev, filename); - break; - } - - return; -} - static void event_queue_delete(struct udev_event *event) { udev_list_node_remove(&event->node); /* mark as failed, if "add" event returns non-zero */ if (event->exitstatus && strcmp(udev_device_get_action(event->dev), "add") == 0) - export_event_state(event, EVENT_FAILED); + udev_queue_export_device_failed(udev_queue_export, event->dev); else - export_event_state(event, EVENT_FINISHED); + udev_queue_export_device_finished(udev_queue_export, event->dev); udev_device_unref(event->dev); udev_event_unref(event); @@ -184,6 +114,16 @@ static void event_fork(struct udev_event *event) struct sigaction act; int err; +#if 0 + /* single process, no forking, just for testing/profiling */ + err = udev_event_execute_rules(event, rules); + if (err == 0 && !event->ignore_device && udev_get_run(event->udev)) + udev_event_execute_run(event); + info(event->udev, "seq %llu exit with %i\n", udev_device_get_seqnum(event->dev), err); + event_queue_delete(event); + return; +#endif + if (debug_trace) { event->trace = 1; fprintf(stderr, "fork %s (%llu)\n", @@ -195,6 +135,7 @@ static void event_fork(struct udev_event *event) switch (pid) { case 0: /* child */ + udev_queue_export_unref(udev_queue_export); udev_ctrl_unref(udev_ctrl); logging_close(); logging_init("udevd-event"); @@ -261,28 +202,12 @@ static void event_fork(struct udev_event *event) static void event_queue_insert(struct udev_event *event) { - char filename[UTIL_PATH_SIZE]; - int fd; - event->queue_time = time(NULL); - export_event_state(event, EVENT_QUEUED); + udev_queue_export_device_queued(udev_queue_export, event->dev); info(event->udev, "seq %llu queued, '%s' '%s'\n", udev_device_get_seqnum(event->dev), udev_device_get_action(event->dev), udev_device_get_subsystem(event->dev)); - util_strlcpy(filename, udev_get_dev_path(event->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]; - int len; - - len = sprintf(str, "%llu\n", udev_device_get_seqnum(event->dev)); - write(fd, str, len); - close(fd); - } - - udev_list_node_append(&event->node, &event_list); run_exec_q = 1; @@ -344,8 +269,6 @@ static int devpath_busy(struct udev_event *event) { struct udev_list_node *loop; - if (event->delaying_seqnum > 0) { - } /* check if queue contains events we depend on */ udev_list_node_foreach(loop, &event_list) { struct udev_event *loop_event = node_to_event(loop); @@ -551,8 +474,7 @@ static int handle_inotify(struct udev *udev) int fd; info(udev, "device %s closed, synthesising 'change'\n", udev_device_get_devnode(dev)); - util_strlcpy(filename, udev_device_get_syspath(dev), sizeof(filename)); - util_strlcat(filename, "/uevent", sizeof(filename)); + util_strscpyl(filename, sizeof(filename), udev_device_get_syspath(dev), "/uevent", NULL); fd = open(filename, O_WRONLY); if (fd < 0 || write(fd, "change", 6) < 0) info(udev, "error writing uevent: %m\n"); @@ -635,66 +557,6 @@ static void reap_sigchilds(void) } } -static void cleanup_queue_dir(struct udev *udev) -{ - char dirname[UTIL_PATH_SIZE]; - char filename[UTIL_PATH_SIZE]; - DIR *dir; - - util_strlcpy(filename, udev_get_dev_path(udev), sizeof(filename)); - util_strlcat(filename, "/.udev/uevent_seqnum", sizeof(filename)); - unlink(filename); - - util_strlcpy(dirname, udev_get_dev_path(udev), sizeof(dirname)); - util_strlcat(dirname, "/.udev/queue", sizeof(dirname)); - dir = opendir(dirname); - if (dir != NULL) { - while (1) { - struct dirent *dent; - - dent = readdir(dir); - if (dent == NULL || dent->d_name[0] == '\0') - break; - if (dent->d_name[0] == '.') - continue; - util_strlcpy(filename, dirname, sizeof(filename)); - util_strlcat(filename, "/", sizeof(filename)); - util_strlcat(filename, dent->d_name, sizeof(filename)); - unlink(filename); - } - closedir(dir); - rmdir(dirname); - } -} - -static void export_initial_seqnum(struct udev *udev) -{ - char filename[UTIL_PATH_SIZE]; - int fd; - char seqnum[32]; - ssize_t len = 0; - - 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); - close(fd); - } - if (len <= 0) { - strcpy(seqnum, "0\n"); - len = 3; - } - util_strlcpy(filename, udev_get_dev_path(udev), sizeof(filename)); - util_strlcat(filename, "/.udev/uevent_seqnum", sizeof(filename)); - util_create_path(udev, filename); - fd = open(filename, O_WRONLY|O_TRUNC|O_CREAT, 0644); - if (fd >= 0) { - write(fd, seqnum, len); - close(fd); - } -} - static void startup_log(struct udev *udev) { FILE *f; @@ -705,8 +567,7 @@ static void startup_log(struct udev *udev) 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)); + util_strscpyl(path, sizeof(path), udev_get_sys_path(udev), "/class/mem/null", NULL); if (lstat(path, &statbuf) == 0 && S_ISDIR(statbuf.st_mode)) { const char *depr_str = "udev: missing sysfs features; please update the kernel " @@ -843,8 +704,11 @@ int main(int argc, char *argv[]) goto exit; } udev_list_init(&event_list); - cleanup_queue_dir(udev); - export_initial_seqnum(udev); + udev_queue_export = udev_queue_export_new(udev); + if (udev_queue_export == NULL) { + err(udev, "error creating queue file\n"); + goto exit; + } if (daemonize) { pid_t pid; @@ -917,8 +781,7 @@ int main(int argc, char *argv[]) IN_CREATE | IN_DELETE | IN_MOVE | IN_CLOSE_WRITE); /* watch dynamic rules directory */ - util_strlcpy(filename, udev_get_dev_path(udev), sizeof(filename)); - util_strlcat(filename, "/.udev/rules.d", sizeof(filename)); + util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.udev/rules.d", NULL); inotify_add_watch(inotify_fd, filename, IN_CREATE | IN_DELETE | IN_MOVE | IN_CLOSE_WRITE); } @@ -1034,9 +897,11 @@ handle_signals: settle_pid = 0; } } - cleanup_queue_dir(udev); + udev_queue_export_cleanup(udev_queue_export); rc = 0; exit: + + udev_queue_export_unref(udev_queue_export); udev_rules_unref(rules); udev_ctrl_unref(udev_ctrl); if (inotify_fd >= 0)