chiark / gitweb /
core: rework how we match mount units against each other
[elogind.git] / src / core / job.c
index 990607f990d9eaffcb175e0e358a210c0111f5e1..bf1d95690824818c593ff900a55ab479d40746d2 100644 (file)
@@ -35,7 +35,7 @@
 #include "log.h"
 #include "dbus-job.h"
 #include "special.h"
-#include "sync.h"
+#include "async.h"
 #include "virt.h"
 
 JobBusClient* job_bus_client_new(DBusConnection *connection, const char *name) {
@@ -206,6 +206,7 @@ Job* job_install(Job *j) {
                                                "Merged into running job, re-running: %s/%s as %u",
                                                uj->unit->id, job_type_to_string(uj->type), (unsigned) uj->id);
                                 uj->state = JOB_WAITING;
+                                uj->manager->n_running_jobs--;
                                 return uj;
                         }
                 }
@@ -483,7 +484,7 @@ static void job_change_type(Job *j, JobType newtype) {
 int job_run_and_invalidate(Job *j) {
         int r;
         uint32_t id;
-        Manager *m;
+        Manager *m = j->manager;
 
         assert(j);
         assert(j->installed);
@@ -500,6 +501,7 @@ int job_run_and_invalidate(Job *j) {
                 return -EAGAIN;
 
         j->state = JOB_RUNNING;
+        m->n_running_jobs++;
         job_add_to_dbus_queue(j);
 
         /* While we execute this operation the job might go away (for
@@ -508,7 +510,6 @@ int job_run_and_invalidate(Job *j) {
          * store the id here, so that we can verify the job is still
          * valid. */
         id = j->id;
-        m = j->manager;
 
         switch (j->type) {
 
@@ -558,16 +559,17 @@ int job_run_and_invalidate(Job *j) {
                         r = job_finish_and_invalidate(j, JOB_DONE, true);
                 else if (r == -ENOEXEC)
                         r = job_finish_and_invalidate(j, JOB_SKIPPED, true);
-                else if (r == -EAGAIN)
+                else if (r == -EAGAIN) {
                         j->state = JOB_WAITING;
-                else if (r < 0)
+                        m->n_running_jobs--;
+                } else if (r < 0)
                         r = job_finish_and_invalidate(j, JOB_FAILED, true);
         }
 
         return r;
 }
 
-static const char *job_get_status_message_format(Unit *u, JobType t, JobResult result) {
+_pure_ static const char *job_get_status_message_format(Unit *u, JobType t, JobResult result) {
         const UnitStatusMessageFormats *format_table;
 
         assert(u);
@@ -586,7 +588,7 @@ static const char *job_get_status_message_format(Unit *u, JobType t, JobResult r
         return NULL;
 }
 
-static const char *job_get_status_message_format_try_harder(Unit *u, JobType t, JobResult result) {
+_pure_ static const char *job_get_status_message_format_try_harder(Unit *u, JobType t, JobResult result) {
         const char *format;
 
         assert(u);
@@ -642,20 +644,20 @@ static void job_print_status_message(Unit *u, JobType t, JobResult result) {
 
                 case JOB_DONE:
                         if (u->condition_result)
-                                unit_status_printf(u, ANSI_HIGHLIGHT_GREEN_ON "  OK  " ANSI_HIGHLIGHT_OFF, format, unit_description(u));
+                                unit_status_printf(u, ANSI_GREEN_ON "  OK  " ANSI_HIGHLIGHT_OFF, format);
                         break;
 
                 case JOB_FAILED:
-                        unit_status_printf(u, ANSI_HIGHLIGHT_RED_ON "FAILED" ANSI_HIGHLIGHT_OFF, format, unit_description(u));
-                        unit_status_printf(u, NULL, "See 'systemctl status %s' for details.", u->id);
+                        unit_status_printf(u, ANSI_HIGHLIGHT_RED_ON "FAILED" ANSI_HIGHLIGHT_OFF, format);
+                        manager_status_printf(u->manager, false, NULL, "See 'systemctl status %s' for details.", u->id);
                         break;
 
                 case JOB_DEPENDENCY:
-                        unit_status_printf(u, ANSI_HIGHLIGHT_YELLOW_ON "DEPEND" ANSI_HIGHLIGHT_OFF, format, unit_description(u));
+                        unit_status_printf(u, ANSI_HIGHLIGHT_YELLOW_ON "DEPEND" ANSI_HIGHLIGHT_OFF, format);
                         break;
 
                 case JOB_TIMEOUT:
-                        unit_status_printf(u, ANSI_HIGHLIGHT_RED_ON " TIME " ANSI_HIGHLIGHT_OFF, format, unit_description(u));
+                        unit_status_printf(u, ANSI_HIGHLIGHT_RED_ON " TIME " ANSI_HIGHLIGHT_OFF, format);
                         break;
 
                 default:
@@ -671,12 +673,12 @@ static void job_print_status_message(Unit *u, JobType t, JobResult result) {
                 switch (result) {
 
                 case JOB_TIMEOUT:
-                        unit_status_printf(u, ANSI_HIGHLIGHT_RED_ON " TIME " ANSI_HIGHLIGHT_OFF, format, unit_description(u));
+                        unit_status_printf(u, ANSI_HIGHLIGHT_RED_ON " TIME " ANSI_HIGHLIGHT_OFF, format);
                         break;
 
                 case JOB_DONE:
                 case JOB_FAILED:
-                        unit_status_printf(u, ANSI_HIGHLIGHT_GREEN_ON "  OK  " ANSI_HIGHLIGHT_OFF, format, unit_description(u));
+                        unit_status_printf(u, ANSI_GREEN_ON "  OK  " ANSI_HIGHLIGHT_OFF, format);
                         break;
 
                 default:
@@ -689,7 +691,7 @@ static void job_print_status_message(Unit *u, JobType t, JobResult result) {
                  * Most likely a DEPEND warning from a requisiting unit will
                  * occur next and it's nice to see what was requisited. */
                 if (result == JOB_SKIPPED)
-                        unit_status_printf(u, ANSI_HIGHLIGHT_ON " INFO " ANSI_HIGHLIGHT_OFF, "%s is not active.", unit_description(u));
+                        unit_status_printf(u, ANSI_HIGHLIGHT_ON " INFO " ANSI_HIGHLIGHT_OFF, "%s is not active.");
         }
 }
 
@@ -760,6 +762,9 @@ int job_finish_and_invalidate(Job *j, JobResult result, bool recursive) {
 
         j->result = result;
 
+        if (j->state == JOB_RUNNING)
+                j->manager->n_running_jobs--;
+
         log_debug_unit(u->id, "Job %s/%s finished, result=%s",
                        u->id, job_type_to_string(t), job_result_to_string(result));
 
@@ -835,9 +840,11 @@ int job_finish_and_invalidate(Job *j, JobResult result, bool recursive) {
                            job_result_to_string(result),
                            NULL);
 
-                unit_trigger_on_failure(u);
+                unit_start_on_failure(u);
         }
 
+        unit_trigger_notify(u);
+
 finish:
         /* Try to start the next jobs that can be started */
         SET_FOREACH(other, u->dependencies[UNIT_AFTER], i)
@@ -853,10 +860,12 @@ finish:
 }
 
 int job_start_timer(Job *j) {
-        struct itimerspec its;
-        struct epoll_event ev;
+        struct itimerspec its = {};
+        struct epoll_event ev = {
+                .data.ptr = &j->timer_watch,
+                .events = EPOLLIN,
+        };
         int fd, r;
-        assert(j);
 
         if (j->unit->job_timeout <= 0 ||
             j->timer_watch.type == WATCH_JOB_TIMER)
@@ -869,7 +878,6 @@ int job_start_timer(Job *j) {
                 goto fail;
         }
 
-        zero(its);
         timespec_store(&its.it_value, j->unit->job_timeout);
 
         if (timerfd_settime(fd, 0, &its, NULL) < 0) {
@@ -877,10 +885,6 @@ int job_start_timer(Job *j) {
                 goto fail;
         }
 
-        zero(ev);
-        ev.data.ptr = &j->timer_watch;
-        ev.events = EPOLLIN;
-
         if (epoll_ctl(j->manager->epoll_fd, EPOLL_CTL_ADD, fd, &ev) < 0) {
                 r = -errno;
                 goto fail;
@@ -1059,15 +1063,14 @@ int job_deserialize(Job *j, FILE *f, FDSet *fds) {
 }
 
 int job_coldplug(Job *j) {
-        struct epoll_event ev;
+        struct epoll_event ev = {
+                .data.ptr = &j->timer_watch,
+                .events = EPOLLIN,
+        };
 
         if (j->timer_watch.type != WATCH_JOB_TIMER)
                 return 0;
 
-        zero(ev);
-        ev.data.ptr = &j->timer_watch;
-        ev.events = EPOLLIN;
-
         if (epoll_ctl(j->manager->epoll_fd, EPOLL_CTL_ADD, j->timer_watch.fd, &ev) < 0)
                 return -errno;
 
@@ -1085,10 +1088,13 @@ void job_shutdown_magic(Job *j) {
          * asynchronous sync() would cause their exit to be
          * delayed. */
 
-        if (!unit_has_name(j->unit, SPECIAL_SHUTDOWN_TARGET))
+        if (j->type != JOB_START)
                 return;
 
-        if (j->type != JOB_START)
+        if (j->unit->manager->running_as != SYSTEMD_SYSTEM)
+                return;
+
+        if (!unit_has_name(j->unit, SPECIAL_SHUTDOWN_TARGET))
                 return;
 
         if (detect_container(NULL) > 0)