X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fcore%2Fpath.c;h=e5ea79fec7c9bf074c781a8e2fc3a55ebf843de9;hp=8a09deb4ff5bbc3fc48ec0c6d49f981141052e23;hb=615938651d3a4fd9253b08da00db22d451a8cef8;hpb=44a6b1b68029833893f6e9cee35aa27a974038f6 diff --git a/src/core/path.c b/src/core/path.c index 8a09deb4f..e5ea79fec 100644 --- a/src/core/path.c +++ b/src/core/path.c @@ -31,9 +31,10 @@ #include "mkdir.h" #include "dbus-path.h" #include "special.h" -#include "dbus-common.h" #include "path-util.h" #include "macro.h" +#include "bus-util.h" +#include "bus-error.h" static const UnitActiveState state_translation_table[_PATH_STATE_MAX] = { [PATH_DEAD] = UNIT_INACTIVE, @@ -42,7 +43,9 @@ static const UnitActiveState state_translation_table[_PATH_STATE_MAX] = { [PATH_FAILED] = UNIT_FAILED }; -int path_spec_watch(PathSpec *s, Unit *u) { +static int path_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata); + +int path_spec_watch(PathSpec *s, sd_event_io_handler_t handler) { static const int flags_table[_PATH_TYPE_MAX] = { [PATH_EXISTS] = IN_DELETE_SELF|IN_MOVE_SELF|IN_ATTRIB, @@ -56,10 +59,11 @@ int path_spec_watch(PathSpec *s, Unit *u) { char *slash, *oldslash = NULL; int r; - assert(u); assert(s); + assert(s->unit); + assert(handler); - path_spec_unwatch(s, u); + path_spec_unwatch(s); s->inotify_fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC); if (s->inotify_fd < 0) { @@ -67,7 +71,7 @@ int path_spec_watch(PathSpec *s, Unit *u) { goto fail; } - r = unit_watch_fd(u, s->inotify_fd, EPOLLIN, &s->watch); + r = sd_event_add_io(s->unit->manager->event, &s->event_source, s->inotify_fd, EPOLLIN, handler, s); if (r < 0) goto fail; @@ -95,7 +99,8 @@ int path_spec_watch(PathSpec *s, Unit *u) { break; } - log_warning("Failed to add watch on %s: %m", s->path); + log_warning("Failed to add watch on %s: %s", s->path, + errno == ENOSPC ? "too many watches" : strerror(-r)); r = -errno; if (cut) *cut = tmp; @@ -131,7 +136,7 @@ int path_spec_watch(PathSpec *s, Unit *u) { } if (!exists) { - log_error("Failed to add watch on any of the components of %s: %m", + log_error_errno(errno, "Failed to add watch on any of the components of %s: %m", s->path); r = -errno; /* either EACCESS or ENOENT */ goto fail; @@ -140,64 +145,40 @@ int path_spec_watch(PathSpec *s, Unit *u) { return 0; fail: - path_spec_unwatch(s, u); + path_spec_unwatch(s); return r; } -void path_spec_unwatch(PathSpec *s, Unit *u) { - - if (s->inotify_fd < 0) - return; - - unit_unwatch_fd(u, &s->watch); +void path_spec_unwatch(PathSpec *s) { + assert(s); - close_nointr_nofail(s->inotify_fd); - s->inotify_fd = -1; + s->event_source = sd_event_source_unref(s->event_source); + s->inotify_fd = safe_close(s->inotify_fd); } -int path_spec_fd_event(PathSpec *s, uint32_t events) { - _cleanup_free_ uint8_t *buf = NULL; +int path_spec_fd_event(PathSpec *s, uint32_t revents) { + union inotify_event_buffer buffer; struct inotify_event *e; - ssize_t k; - int l; + ssize_t l; int r = 0; - if (events != EPOLLIN) { + if (revents != EPOLLIN) { log_error("Got invalid poll event on inotify."); return -EINVAL; } - if (ioctl(s->inotify_fd, FIONREAD, &l) < 0) { - log_error("FIONREAD failed: %m"); - return -errno; - } - - assert(l > 0); - - buf = malloc(l); - if (!buf) - return log_oom(); + l = read(s->inotify_fd, &buffer, sizeof(buffer)); + if (l < 0) { + if (errno == EAGAIN || errno == EINTR) + return 0; - k = read(s->inotify_fd, buf, l); - if (k < 0) { - log_error("Failed to read inotify event: %m"); - return -errno; + return log_error_errno(errno, "Failed to read inotify event: %m"); } - e = (struct inotify_event*) buf; - - while (k > 0) { - size_t step; - + FOREACH_INOTIFY_EVENT(e, buffer, l) { if ((s->type == PATH_CHANGED || s->type == PATH_MODIFIED) && s->primary_wd == e->wd) r = 1; - - step = sizeof(struct inotify_event) + e->len; - assert(step <= (size_t) k); - - e = (struct inotify_event*) ((uint8_t*) e + step); - k -= step; } return r; @@ -241,10 +222,6 @@ static bool path_spec_check_good(PathSpec *s, bool initial) { return good; } -static bool path_spec_startswith(PathSpec *s, const char *what) { - return path_startswith(s->path, what); -} - static void path_spec_mkdir(PathSpec *s, mode_t mode) { int r; @@ -253,7 +230,7 @@ static void path_spec_mkdir(PathSpec *s, mode_t mode) { r = mkdir_p_label(s->path, mode); if (r < 0) - log_warning("mkdir(%s) failed: %s", s->path, strerror(-r)); + log_warning_errno(r, "mkdir(%s) failed: %m", s->path); } static void path_spec_dump(PathSpec *s, FILE *f, const char *prefix) { @@ -286,8 +263,8 @@ void path_free_specs(Path *p) { assert(p); while ((s = p->specs)) { - path_spec_unwatch(s, UNIT(p)); - LIST_REMOVE(PathSpec, spec, p->specs, s); + path_spec_unwatch(s); + LIST_REMOVE(spec, p->specs, s); path_spec_done(s); free(s); } @@ -301,38 +278,14 @@ static void path_done(Unit *u) { path_free_specs(p); } -int path_add_one_mount_link(Path *p, Mount *m) { +static int path_add_mount_links(Path *p) { PathSpec *s; int r; assert(p); - assert(m); - - if (UNIT(p)->load_state != UNIT_LOADED || - UNIT(m)->load_state != UNIT_LOADED) - return 0; LIST_FOREACH(spec, s, p->specs) { - if (!path_spec_startswith(s, m->where)) - continue; - - r = unit_add_two_dependencies(UNIT(p), UNIT_AFTER, UNIT_REQUIRES, - UNIT(m), true); - if (r < 0) - return r; - } - - return 0; -} - -static int path_add_mount_links(Path *p) { - Unit *other; - int r; - - assert(p); - - LIST_FOREACH(units_by_type, other, UNIT(p)->manager->units_by_type[UNIT_MOUNT]) { - r = path_add_one_mount_link(p, MOUNT(other)); + r = unit_require_mounts_for(UNIT(p), s->path); if (r < 0) return r; } @@ -347,7 +300,7 @@ static int path_verify(Path *p) { return 0; if (!p->specs) { - log_error_unit(UNIT(p)->id, + log_unit_error(UNIT(p)->id, "%s lacks path setting. Refusing.", UNIT(p)->id); return -EINVAL; } @@ -447,7 +400,7 @@ static void path_unwatch(Path *p) { assert(p); LIST_FOREACH(spec, s, p->specs) - path_spec_unwatch(s, UNIT(p)); + path_spec_unwatch(s); } static int path_watch(Path *p) { @@ -457,7 +410,7 @@ static int path_watch(Path *p) { assert(p); LIST_FOREACH(spec, s, p->specs) { - r = path_spec_watch(s, UNIT(p)); + r = path_spec_watch(s, path_dispatch_io); if (r < 0) return r; } @@ -515,13 +468,11 @@ static void path_enter_dead(Path *p, PathResult f) { } static void path_enter_running(Path *p) { - _cleanup_dbus_error_free_ DBusError error; + _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; int r; assert(p); - dbus_error_init(&error); - /* Don't start job if we are supposed to go down */ if (unit_stop_pending(UNIT(p))) return; @@ -542,7 +493,7 @@ static void path_enter_running(Path *p) { fail: log_warning("%s failed to queue unit startup job: %s", - UNIT(p)->id, bus_error(&error, r)); + UNIT(p)->id, bus_error_message(&error, r)); path_enter_dead(p, PATH_FAILURE_RESOURCES); } @@ -591,8 +542,7 @@ static void path_enter_waiting(Path *p, bool initial, bool recheck) { return; fail: - log_warning("%s failed to enter waiting state: %s", - UNIT(p)->id, strerror(-r)); + log_warning_errno(r, "%s failed to enter waiting state: %m", UNIT(p)->id); path_enter_dead(p, PATH_FAILURE_RESOURCES); } @@ -622,7 +572,7 @@ static int path_start(Unit *u) { p->result = PATH_SUCCESS; path_enter_waiting(p, true, true); - return 0; + return 1; } static int path_stop(Unit *u) { @@ -632,7 +582,7 @@ static int path_stop(Unit *u) { assert(p->state == PATH_WAITING || p->state == PATH_RUNNING); path_enter_dead(p, PATH_SUCCESS); - return 0; + return 1; } static int path_serialize(Unit *u, FILE *f, FDSet *fds) { @@ -692,17 +642,20 @@ _pure_ static const char *path_sub_state_to_string(Unit *u) { return path_state_to_string(PATH(u)->state); } -static void path_fd_event(Unit *u, int fd, uint32_t events, Watch *w) { - Path *p = PATH(u); - PathSpec *s; +static int path_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) { + PathSpec *s = userdata; + Path *p; int changed; - assert(p); + assert(s); + assert(s->unit); assert(fd >= 0); + p = PATH(s->unit); + if (p->state != PATH_WAITING && p->state != PATH_RUNNING) - return; + return 0; /* log_debug("inotify wakeup on %s.", u->id); */ @@ -715,7 +668,7 @@ static void path_fd_event(Unit *u, int fd, uint32_t events, Watch *w) { goto fail; } - changed = path_spec_fd_event(s, events); + changed = path_spec_fd_event(s, revents); if (changed < 0) goto fail; @@ -729,10 +682,11 @@ static void path_fd_event(Unit *u, int fd, uint32_t events, Watch *w) { else path_enter_waiting(p, false, true); - return; + return 0; fail: path_enter_dead(p, PATH_FAILURE_RESOURCES); + return 0; } static void path_trigger_notify(Unit *u, Unit *other) { @@ -749,7 +703,7 @@ static void path_trigger_notify(Unit *u, Unit *other) { if (p->state == PATH_RUNNING && UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other))) { - log_debug_unit(UNIT(p)->id, + log_unit_debug(UNIT(p)->id, "%s got notified about unit deactivation.", UNIT(p)->id); @@ -783,22 +737,23 @@ DEFINE_STRING_TABLE_LOOKUP(path_state, PathState); static const char* const path_type_table[_PATH_TYPE_MAX] = { [PATH_EXISTS] = "PathExists", [PATH_EXISTS_GLOB] = "PathExistsGlob", + [PATH_DIRECTORY_NOT_EMPTY] = "DirectoryNotEmpty", [PATH_CHANGED] = "PathChanged", [PATH_MODIFIED] = "PathModified", - [PATH_DIRECTORY_NOT_EMPTY] = "DirectoryNotEmpty" }; DEFINE_STRING_TABLE_LOOKUP(path_type, PathType); static const char* const path_result_table[_PATH_RESULT_MAX] = { [PATH_SUCCESS] = "success", - [PATH_FAILURE_RESOURCES] = "resources" + [PATH_FAILURE_RESOURCES] = "resources", }; DEFINE_STRING_TABLE_LOOKUP(path_result, PathResult); const UnitVTable path_vtable = { .object_size = sizeof(Path), + .sections = "Unit\0" "Path\0" @@ -821,13 +776,10 @@ const UnitVTable path_vtable = { .active_state = path_active_state, .sub_state_to_string = path_sub_state_to_string, - .fd_event = path_fd_event, - .trigger_notify = path_trigger_notify, .reset_failed = path_reset_failed, .bus_interface = "org.freedesktop.systemd1.Path", - .bus_message_handler = bus_path_message_handler, - .bus_invalidating_properties = bus_path_invalidating_properties + .bus_vtable = bus_path_vtable };