#include "unit.h"
#include "macro.h"
#include "strv.h"
+#include "path-util.h"
#include "load-fragment.h"
#include "load-dropin.h"
#include "log.h"
if (u->job)
return true;
+ if (u->nop_job)
+ return true;
+
if (unit_active_state(u) != UNIT_INACTIVE)
return true;
SET_FOREACH(t, u->names, i)
hashmap_remove_value(u->manager->units, t, u);
- if (u->job)
- job_free(u->job);
+ if (u->job) {
+ Job *j = u->job;
+ job_uninstall(j);
+ job_free(j);
+ }
+
+ if (u->nop_job) {
+ Job *j = u->nop_job;
+ job_uninstall(j);
+ job_free(j);
+ }
for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++)
bidi_set_free(u, u->dependencies[d]);
+ if (u->requires_mounts_for) {
+ LIST_REMOVE(Unit, has_requires_mounts_for, u->manager->has_requires_mounts_for, u);
+ strv_free(u->requires_mounts_for);
+ }
+
if (u->type != _UNIT_TYPE_INVALID)
LIST_REMOVE(Unit, units_by_type, u->manager->units_by_type[u->type], u);
cgroup_attribute_free_list(u->cgroup_attributes);
free(u->description);
+ strv_free(u->documentation);
free(u->fragment_path);
free(u->instance);
if (other->job)
return -EEXIST;
+ if (other->nop_job)
+ return -EEXIST;
+
if (!UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other)))
return -EEXIST;
}
void unit_dump(Unit *u, FILE *f, const char *prefix) {
- char *t;
+ char *t, **j;
UnitDependency d;
Iterator i;
char *p2;
SET_FOREACH(t, u->names, i)
fprintf(f, "%s\tName: %s\n", prefix, t);
+ STRV_FOREACH(j, u->documentation)
+ fprintf(f, "%s\tDocumentation: %s\n", prefix, *j);
+
if ((following = unit_following(u)))
fprintf(f, "%s\tFollowing: %s\n", prefix, following->id);
fprintf(f, "%s\t%s: %s\n", prefix, unit_dependency_to_string(d), other->id);
}
+ if (!strv_isempty(u->requires_mounts_for)) {
+ fprintf(f,
+ "%s\tRequiresMountsFor:", prefix);
+
+ STRV_FOREACH(j, u->requires_mounts_for)
+ fprintf(f, " %s", *j);
+
+ fputs("\n", f);
+ }
+
if (u->load_state == UNIT_LOADED) {
CGroupBonding *b;
CGroupAttribute *a;
if (u->job)
job_dump(u->job, f, prefix2);
+ if (u->nop_job)
+ job_dump(u->nop_job, f, prefix2);
+
free(p2);
}
if ((r = unit_add_default_dependencies(u)) < 0)
goto fail;
+ if (u->load_state == UNIT_LOADED) {
+ r = unit_add_mount_links(u);
+ if (r < 0)
+ return r;
+ }
+
if (u->on_failure_isolate &&
set_size(u->dependencies[UNIT_ON_FAILURE]) > 1) {
return u->condition_result;
}
+static void unit_status_print_starting_stopping(Unit *u, bool stopping) {
+ const UnitStatusMessageFormats *format_table;
+ const char *format;
+
+ format_table = &UNIT_VTABLE(u)->status_message_formats;
+ if (!format_table)
+ return;
+
+ format = format_table->starting_stopping[stopping];
+ if (!format)
+ return;
+
+ unit_status_printf(u, "", format, unit_description(u));
+}
+
/* Errors:
* -EBADR: This unit type does not support starting.
* -EALREADY: Unit is already started.
return unit_start(following);
}
+ unit_status_print_starting_stopping(u, false);
+
/* If it is stopped, but we cannot start it, then fail */
if (!UNIT_VTABLE(u)->start)
return -EBADR;
unit_add_to_dbus_queue(u);
- unit_status_printf(u, NULL, "Starting %s...", unit_description(u));
return UNIT_VTABLE(u)->start(u);
}
return unit_stop(following);
}
+ unit_status_print_starting_stopping(u, true);
+
if (!UNIT_VTABLE(u)->stop)
return -EBADR;
unit_add_to_dbus_queue(u);
- unit_status_printf(u, NULL, "Stopping %s...", unit_description(u));
return UNIT_VTABLE(u)->stop(u);
}
case JOB_VERIFY_ACTIVE:
if (UNIT_IS_ACTIVE_OR_RELOADING(ns))
- job_finish_and_invalidate(u->job, JOB_DONE);
+ job_finish_and_invalidate(u->job, JOB_DONE, true);
else if (u->job->state == JOB_RUNNING && ns != UNIT_ACTIVATING) {
unexpected = true;
if (UNIT_IS_INACTIVE_OR_FAILED(ns))
- job_finish_and_invalidate(u->job, ns == UNIT_FAILED ? JOB_FAILED : JOB_DONE);
+ job_finish_and_invalidate(u->job, ns == UNIT_FAILED ? JOB_FAILED : JOB_DONE, true);
}
break;
if (u->job->state == JOB_RUNNING) {
if (ns == UNIT_ACTIVE)
- job_finish_and_invalidate(u->job, reload_success ? JOB_DONE : JOB_FAILED);
+ job_finish_and_invalidate(u->job, reload_success ? JOB_DONE : JOB_FAILED, true);
else if (ns != UNIT_ACTIVATING && ns != UNIT_RELOADING) {
unexpected = true;
if (UNIT_IS_INACTIVE_OR_FAILED(ns))
- job_finish_and_invalidate(u->job, ns == UNIT_FAILED ? JOB_FAILED : JOB_DONE);
+ job_finish_and_invalidate(u->job, ns == UNIT_FAILED ? JOB_FAILED : JOB_DONE, true);
}
}
case JOB_TRY_RESTART:
if (UNIT_IS_INACTIVE_OR_FAILED(ns))
- job_finish_and_invalidate(u->job, JOB_DONE);
+ job_finish_and_invalidate(u->job, JOB_DONE, true);
else if (u->job->state == JOB_RUNNING && ns != UNIT_DEACTIVATING) {
unexpected = true;
- job_finish_and_invalidate(u->job, JOB_FAILED);
+ job_finish_and_invalidate(u->job, JOB_FAILED, true);
}
break;
case JOB_VERIFY_ACTIVE:
case JOB_START:
case JOB_STOP:
+ case JOB_NOP:
return true;
case JOB_RESTART:
assert(name || path);
if (!name)
- name = file_name_from_path(path);
+ name = path_get_file_name(path);
if (!unit_name_is_template(name)) {
*p = NULL;
if (specifier == 'r')
return strdup(u->manager->cgroup_hierarchy);
- if (parent_of_path(u->manager->cgroup_hierarchy, &p) < 0)
+ if (path_get_parent(u->manager->cgroup_hierarchy, &p) < 0)
return strdup("");
if (streq(p, "/")) {
if ((r = UNIT_VTABLE(u)->serialize(u, f, fds)) < 0)
return r;
- if (u->job)
- unit_serialize_item(u, f, "job", job_type_to_string(u->job->type));
+ if (u->job) {
+ fprintf(f, "job\n");
+ job_serialize(u->job, f, fds);
+ }
+
+ if (u->nop_job) {
+ fprintf(f, "job\n");
+ job_serialize(u->nop_job, f, fds);
+ }
dual_timestamp_serialize(f, "inactive-exit-timestamp", &u->inactive_exit_timestamp);
dual_timestamp_serialize(f, "active-enter-timestamp", &u->active_enter_timestamp);
v = l+k;
if (streq(l, "job")) {
- JobType type;
+ if (v[0] == '\0') {
+ /* new-style serialized job */
+ Job *j = job_new_raw(u);
+ if (!j)
+ return -ENOMEM;
+
+ r = job_deserialize(j, f, fds);
+ if (r < 0) {
+ job_free(j);
+ return r;
+ }
- if ((type = job_type_from_string(v)) < 0)
- log_debug("Failed to parse job type value %s", v);
- else
- u->deserialized_job = type;
+ r = hashmap_put(u->manager->jobs, UINT32_TO_PTR(j->id), j);
+ if (r < 0) {
+ job_free(j);
+ return r;
+ }
+ r = job_install_deserialized(j);
+ if (r < 0) {
+ hashmap_remove(u->manager->jobs, UINT32_TO_PTR(j->id));
+ job_free(j);
+ return r;
+ }
+ } else {
+ /* legacy */
+ JobType type = job_type_from_string(v);
+ if (type < 0)
+ log_debug("Failed to parse job type value %s", v);
+ else
+ u->deserialized_job = type;
+ }
continue;
} else if (streq(l, "inactive-exit-timestamp")) {
dual_timestamp_deserialize(v, &u->inactive_exit_timestamp);
if ((r = UNIT_VTABLE(u)->coldplug(u)) < 0)
return r;
- if (u->deserialized_job >= 0) {
- if ((r = manager_add_job(u->manager, u->deserialized_job, u, JOB_IGNORE_REQUIREMENTS, false, NULL, NULL)) < 0)
+ if (u->job) {
+ r = job_coldplug(u->job);
+ if (r < 0)
+ return r;
+ } else if (u->deserialized_job >= 0) {
+ /* legacy */
+ r = manager_add_job(u->manager, u->deserialized_job, u, JOB_IGNORE_REQUIREMENTS, false, NULL, NULL);
+ if (r < 0)
return r;
u->deserialized_job = _JOB_TYPE_INVALID;
assert(u);
assert(format);
- if (!UNIT_VTABLE(u)->show_status)
- return;
-
if (!manager_get_show_status(u->manager))
return;
if (u->unit_file_state < 0 && u->fragment_path)
u->unit_file_state = unit_file_get_state(
u->manager->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER,
- NULL, file_name_from_path(u->fragment_path));
+ NULL, path_get_file_name(u->fragment_path));
return u->unit_file_state;
}
ref->unit = NULL;
}
+int unit_add_one_mount_link(Unit *u, Mount *m) {
+ char **i;
+
+ assert(u);
+ assert(m);
+
+ if (u->load_state != UNIT_LOADED ||
+ UNIT(m)->load_state != UNIT_LOADED)
+ return 0;
+
+ STRV_FOREACH(i, u->requires_mounts_for) {
+
+ if (UNIT(m) == u)
+ continue;
+
+ if (!path_startswith(*i, m->where))
+ continue;
+
+ return unit_add_two_dependencies(u, UNIT_AFTER, UNIT_REQUIRES, UNIT(m), true);
+ }
+
+ return 0;
+}
+
+int unit_add_mount_links(Unit *u) {
+ Unit *other;
+ int r;
+
+ assert(u);
+
+ LIST_FOREACH(units_by_type, other, u->manager->units_by_type[UNIT_MOUNT]) {
+ r = unit_add_one_mount_link(u, MOUNT(other));
+ if (r < 0)
+ return r;
+ }
+
+ return 0;
+}
+
static const char* const unit_load_state_table[_UNIT_LOAD_STATE_MAX] = {
[UNIT_STUB] = "stub",
[UNIT_LOADED] = "loaded",