diff options
author | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2019-11-18 14:13:05 +0100 |
---|---|---|
committer | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2019-11-18 14:13:05 +0100 |
commit | 7a16cd4b05cc3e975d90aee72ed9d77ada22a093 (patch) | |
tree | 70ed5123c7a0e19074d7545ed4e97bd064eeb643 /src/core | |
parent | 6906ac9a6920b1849db51450df7739100c5100ed (diff) | |
download | systemd-7a16cd4b05cc3e975d90aee72ed9d77ada22a093.tar.gz |
core/path: serialize the previous_exists state
Without that we are prone to generate spurious events after daemon
reload/restart.
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/path.c | 55 |
1 files changed, 51 insertions, 4 deletions
diff --git a/src/core/path.c b/src/core/path.c index dff551f377..ed3a0132c2 100644 --- a/src/core/path.c +++ b/src/core/path.c @@ -9,12 +9,14 @@ #include "bus-util.h" #include "dbus-path.h" #include "dbus-unit.h" +#include "escape.h" #include "fd-util.h" #include "fs-util.h" #include "glob-util.h" #include "macro.h" #include "mkdir.h" #include "path.h" +#include "path-util.h" #include "serialize.h" #include "special.h" #include "stat-util.h" @@ -27,19 +29,18 @@ static const UnitActiveState state_translation_table[_PATH_STATE_MAX] = { [PATH_DEAD] = UNIT_INACTIVE, [PATH_WAITING] = UNIT_ACTIVE, [PATH_RUNNING] = UNIT_ACTIVE, - [PATH_FAILED] = UNIT_FAILED + [PATH_FAILED] = UNIT_FAILED, }; 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, [PATH_EXISTS_GLOB] = IN_DELETE_SELF|IN_MOVE_SELF|IN_ATTRIB, [PATH_CHANGED] = IN_DELETE_SELF|IN_MOVE_SELF|IN_ATTRIB|IN_CLOSE_WRITE|IN_CREATE|IN_DELETE|IN_MOVED_FROM|IN_MOVED_TO, [PATH_MODIFIED] = IN_DELETE_SELF|IN_MOVE_SELF|IN_ATTRIB|IN_CLOSE_WRITE|IN_CREATE|IN_DELETE|IN_MOVED_FROM|IN_MOVED_TO|IN_MODIFY, - [PATH_DIRECTORY_NOT_EMPTY] = IN_DELETE_SELF|IN_MOVE_SELF|IN_ATTRIB|IN_CREATE|IN_MOVED_TO + [PATH_DIRECTORY_NOT_EMPTY] = IN_DELETE_SELF|IN_MOVE_SELF|IN_ATTRIB|IN_CREATE|IN_MOVED_TO, }; bool exists = false; @@ -601,6 +602,7 @@ static int path_stop(Unit *u) { static int path_serialize(Unit *u, FILE *f, FDSet *fds) { Path *p = PATH(u); + PathSpec *s; assert(u); assert(f); @@ -609,6 +611,19 @@ static int path_serialize(Unit *u, FILE *f, FDSet *fds) { (void) serialize_item(f, "state", path_state_to_string(p->state)); (void) serialize_item(f, "result", path_result_to_string(p->result)); + LIST_FOREACH(spec, s, p->specs) { + _cleanup_free_ char *escaped = NULL; + + escaped = cescape(s->path); + if (!escaped) + return log_oom(); + + (void) serialize_item_format(f, "path-spec", "%s %i %s", + path_type_to_string(s->type), + s->previous_exists, + s->path); + } + return 0; } @@ -638,6 +653,38 @@ static int path_deserialize_item(Unit *u, const char *key, const char *value, FD else if (f != PATH_SUCCESS) p->result = f; + } else if (streq(key, "path-spec")) { + int previous_exists, skip = 0, r; + _cleanup_free_ char *type_str = NULL; + + if (sscanf(value, "%ms %i %n", &type_str, &previous_exists, &skip) < 2) + log_unit_debug(u, "Failed to parse path-spec value: %s", value); + else { + _cleanup_free_ char *unescaped = NULL; + PathType type; + PathSpec *s; + + type = path_type_from_string(type_str); + if (type < 0) { + log_unit_warning(u, "Unknown path type \"%s\", ignoring.", type_str); + return 0; + } + + r = cunescape(value+skip, 0, &unescaped); + if (r < 0) { + log_unit_warning_errno(u, r, "Failed to unescape serialize path: %m"); + return 0; + } + + LIST_FOREACH(spec, s, p->specs) + if (s->type == type && + path_equal(s->path, unescaped)) { + + s->previous_exists = previous_exists; + break; + } + } + } else log_unit_debug(u, "Unknown serialization key: %s", key); @@ -670,7 +717,7 @@ static int path_dispatch_io(sd_event_source *source, int fd, uint32_t revents, v if (!IN_SET(p->state, PATH_WAITING, PATH_RUNNING)) return 0; - /* log_debug("inotify wakeup on %s.", u->id); */ + /* log_debug("inotify wakeup on %s.", UNIT(p)->id); */ LIST_FOREACH(spec, s, p->specs) if (path_spec_owns_inotify_fd(s, fd)) |