#include "load-dropin.h"
#include "log.h"
#include "dbus-job.h"
+#include "special.h"
+#include "sync.h"
+#include "virt.h"
JobBusClient* job_bus_client_new(DBusConnection *connection, const char *name) {
JobBusClient *cl;
assert(other->type == JOB_NOP);
j->override = j->override || other->override;
+ j->ignore_order = j->ignore_order || other->ignore_order;
}
Job* job_install(Job *j) {
sd_id128_t mid;
mid = result == JOB_DONE ? SD_MESSAGE_UNIT_STARTED : SD_MESSAGE_UNIT_FAILED;
- log_struct(result == JOB_DONE ? LOG_INFO : LOG_ERR,
+ log_struct_unit(result == JOB_DONE ? LOG_INFO : LOG_ERR,
+ u->id,
MESSAGE_ID(mid),
- "UNIT=%s", u->id,
"RESULT=%s", job_result_to_string(result),
"MESSAGE=%s", buf,
NULL);
} else if (t == JOB_STOP)
- log_struct(result == JOB_DONE ? LOG_INFO : LOG_ERR,
+ log_struct_unit(result == JOB_DONE ? LOG_INFO : LOG_ERR,
+ u->id,
MESSAGE_ID(SD_MESSAGE_UNIT_STOPPED),
- "UNIT=%s", u->id,
"RESULT=%s", job_result_to_string(result),
"MESSAGE=%s", buf,
NULL);
else if (t == JOB_RELOAD)
- log_struct(result == JOB_DONE ? LOG_INFO : LOG_ERR,
+ log_struct_unit(result == JOB_DONE ? LOG_INFO : LOG_ERR,
+ u->id,
MESSAGE_ID(SD_MESSAGE_UNIT_RELOADED),
- "UNIT=%s", u->id,
"RESULT=%s", job_result_to_string(result),
"MESSAGE=%s", buf,
NULL);
* this context. And JOB_FAILURE is already handled by the
* unit itself. */
if (result == JOB_TIMEOUT || result == JOB_DEPENDENCY) {
- log_struct(LOG_NOTICE,
- "UNIT=%s", u->id,
+ log_struct_unit(LOG_NOTICE,
+ u->id,
"JOB_TYPE=%s", job_type_to_string(t),
- "JOB_RESULT=%s", job_result_to_string(t),
+ "JOB_RESULT=%s", job_result_to_string(result),
"Job %s/%s failed with result '%s'.",
u->id,
job_type_to_string(t),
return 0;
}
+void job_shutdown_magic(Job *j) {
+ assert(j);
+
+ /* The shutdown target gets some special treatment here: we
+ * tell the kernel to begin with flushing its disk caches, to
+ * optimize shutdown time a bit. Ideally we wouldn't hardcode
+ * this magic into PID 1. However all other processes aren't
+ * options either since they'd exit much sooner than PID 1 and
+ * asynchronous sync() would cause their exit to be
+ * delayed. */
+
+ if (!unit_has_name(j->unit, SPECIAL_SHUTDOWN_TARGET))
+ return;
+
+ if (j->type != JOB_START)
+ return;
+
+ if (detect_container(NULL) > 0)
+ return;
+
+ asynchronous_sync();
+}
+
static const char* const job_state_table[_JOB_STATE_MAX] = {
[JOB_WAITING] = "waiting",
[JOB_RUNNING] = "running"