chiark / gitweb /
hwclock: add taint flag for non-local hwclock
[elogind.git] / src / core / unit.c
index 9e33701c8f4886b0af60a3c31aaee61d0da34142..fea75e88fe6fa4dbaafd0ea50588d73ef64c1d37 100644 (file)
@@ -6,16 +6,16 @@
   Copyright 2010 Lennart Poettering
 
   systemd is free software; you can redistribute it and/or modify it
-  under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
   (at your option) any later version.
 
   systemd is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-  General Public License for more details.
+  Lesser General Public License for more details.
 
-  You should have received a copy of the GNU General Public License
+  You should have received a copy of the GNU Lesser General Public License
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
@@ -249,6 +249,9 @@ bool unit_check_gc(Unit *u) {
         if (u->job)
                 return true;
 
+        if (u->nop_job)
+                return true;
+
         if (unit_active_state(u) != UNIT_INACTIVE)
                 return true;
 
@@ -352,12 +355,26 @@ void unit_free(Unit *u) {
         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);
 
@@ -498,6 +515,9 @@ int unit_merge(Unit *u, Unit *other) {
         if (other->job)
                 return -EEXIST;
 
+        if (other->nop_job)
+                return -EEXIST;
+
         if (!UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other)))
                 return -EEXIST;
 
@@ -676,6 +696,18 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) {
                         fprintf(f, "%s\t%s: %s\n", prefix, unit_dependency_to_string(d), other->id);
         }
 
+        if (!strv_isempty(u->requires_mounts_for)) {
+                char **j;
+
+                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;
@@ -726,6 +758,9 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) {
         if (u->job)
                 job_dump(u->job, f, prefix2);
 
+        if (u->nop_job)
+                job_dump(u->nop_job, f, prefix2);
+
         free(p2);
 }
 
@@ -851,6 +886,12 @@ int unit_load(Unit *u) {
                 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) {
 
@@ -1223,12 +1264,12 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_su
                 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;
@@ -1238,12 +1279,12 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_su
 
                         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);
                                 }
                         }
 
@@ -1254,10 +1295,10 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_su
                 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;
@@ -1504,6 +1545,7 @@ bool unit_job_is_applicable(Unit *u, JobType j) {
         case JOB_VERIFY_ACTIVE:
         case JOB_START:
         case JOB_STOP:
+        case JOB_NOP:
                 return true;
 
         case JOB_RESTART:
@@ -2285,8 +2327,15 @@ int unit_serialize(Unit *u, FILE *f, FDSet *fds) {
         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);
@@ -2365,13 +2414,38 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds) {
                         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);
@@ -2447,8 +2521,14 @@ int unit_coldplug(Unit *u) {
                 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;
@@ -2628,6 +2708,45 @@ void unit_ref_unset(UnitRef *ref) {
         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",