X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fcore%2Fmanager.c;h=f56d39007a0ae1678f3c146eb602576c828d7f88;hb=c3090674833c8bd34fbdb0e743f1c47d85dd14fb;hp=5c6d63668d7491f821281af736f555901184887a;hpb=07719a21b6425d378b36bb8d7f47ad5ec5296d28;p=elogind.git diff --git a/src/core/manager.c b/src/core/manager.c index 5c6d63668..f56d39007 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -41,7 +41,9 @@ #include #endif -#include +#include "systemd/sd-daemon.h" +#include "systemd/sd-id128.h" +#include "systemd/sd-messages.h" #include "manager.h" #include "transaction.h" @@ -74,8 +76,7 @@ #define GC_QUEUE_USEC_MAX (10*USEC_PER_SEC) /* Where clients shall send notification messages to */ -#define NOTIFY_SOCKET_SYSTEM "/run/systemd/notify" -#define NOTIFY_SOCKET_USER "@/org/freedesktop/systemd1/notify" +#define NOTIFY_SOCKET "@/org/freedesktop/systemd1/notify" static int manager_setup_notify(Manager *m) { union { @@ -83,13 +84,13 @@ static int manager_setup_notify(Manager *m) { struct sockaddr_un un; } sa; struct epoll_event ev; - int one = 1, r; - mode_t u; + int one = 1; assert(m); m->notify_watch.type = WATCH_NOTIFY; - if ((m->notify_watch.fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0)) < 0) { + m->notify_watch.fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); + if (m->notify_watch.fd < 0) { log_error("Failed to allocate notification socket: %m"); return -errno; } @@ -97,21 +98,14 @@ static int manager_setup_notify(Manager *m) { zero(sa); sa.sa.sa_family = AF_UNIX; - if (getpid() != 1) - snprintf(sa.un.sun_path, sizeof(sa.un.sun_path), NOTIFY_SOCKET_USER "/%llu", random_ull()); - else { - unlink(NOTIFY_SOCKET_SYSTEM); - strncpy(sa.un.sun_path, NOTIFY_SOCKET_SYSTEM, sizeof(sa.un.sun_path)); - } - - if (sa.un.sun_path[0] == '@') - sa.un.sun_path[0] = 0; + if (getpid() != 1 || detect_container(NULL) > 0) + snprintf(sa.un.sun_path, sizeof(sa.un.sun_path), NOTIFY_SOCKET "/%llu", random_ull()); + else + strncpy(sa.un.sun_path, NOTIFY_SOCKET, sizeof(sa.un.sun_path)); - u = umask(0111); - r = bind(m->notify_watch.fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + 1 + strlen(sa.un.sun_path+1)); - umask(u); + sa.un.sun_path[0] = 0; - if (r < 0) { + if (bind(m->notify_watch.fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + 1 + strlen(sa.un.sun_path+1)) < 0) { log_error("bind() failed: %m"); return -errno; } @@ -128,10 +122,9 @@ static int manager_setup_notify(Manager *m) { if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->notify_watch.fd, &ev) < 0) return -errno; - if (sa.un.sun_path[0] == 0) - sa.un.sun_path[0] = '@'; - - if (!(m->notify_socket = strdup(sa.un.sun_path))) + sa.un.sun_path[0] = '@'; + m->notify_socket = strdup(sa.un.sun_path); + if (!m->notify_socket) return -ENOMEM; log_debug("Using notification socket %s", m->notify_socket); @@ -145,8 +138,9 @@ static int enable_special_signals(Manager *m) { assert(m); /* Enable that we get SIGINT on control-alt-del. In containers - * this will fail with EPERM, so ignore that. */ - if (reboot(RB_DISABLE_CAD) < 0 && errno != EPERM) + * this will fail with EPERM (older) or EINVAL (newer), so + * ignore that. */ + if (reboot(RB_DISABLE_CAD) < 0 && errno != EPERM && errno != EINVAL) log_warning("Failed to enable ctrl-alt-del handling: %m"); fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC); @@ -251,10 +245,11 @@ int manager_new(ManagerRunningAs running_as, Manager **_m) { assert(running_as >= 0); assert(running_as < _MANAGER_RUNNING_AS_MAX); - if (!(m = new0(Manager, 1))) + m = new0(Manager, 1); + if (!m) return -ENOMEM; - dual_timestamp_get(&m->startup_timestamp); + dual_timestamp_get(&m->userspace_timestamp); m->running_as = running_as; m->name_data_slot = m->conn_data_slot = m->subscribed_data_slot = -1; @@ -599,7 +594,7 @@ static void manager_build_unit_path_cache(Manager *m) { if (ignore_file(de->d_name)) continue; - p = join(streq(*i, "/") ? "" : *i, "/", de->d_name, NULL); + p = strjoin(streq(*i, "/") ? "" : *i, "/", de->d_name, NULL); if (!p) { r = -ENOMEM; goto fail; @@ -739,7 +734,8 @@ int manager_add_job_by_name(Manager *m, JobType type, const char *name, JobMode assert(name); assert(mode < _JOB_MODE_MAX); - if ((r = manager_load_unit(m, name, NULL, NULL, &unit)) < 0) + r = manager_load_unit(m, name, NULL, NULL, &unit); + if (r < 0) return r; return manager_add_job(m, type, unit, mode, override, e, _ret); @@ -805,7 +801,7 @@ int manager_load_unit_prepare(Manager *m, const char *name, const char *path, DB t = unit_name_to_type(name); - if (t == _UNIT_TYPE_INVALID || !unit_name_is_valid_no_type(name, false)) { + if (t == _UNIT_TYPE_INVALID || !unit_name_is_valid(name, false)) { dbus_set_error(e, BUS_ERROR_INVALID_NAME, "Unit name %s is not valid.", name); return -EINVAL; } @@ -851,7 +847,8 @@ int manager_load_unit(Manager *m, const char *name, const char *path, DBusError /* This will load the service information files, but not actually * start any services or anything. */ - if ((r = manager_load_unit_prepare(m, name, path, e, _ret)) != 0) + r = manager_load_unit_prepare(m, name, path, e, _ret); + if (r != 0) return r; manager_dispatch_load_queue(m); @@ -1634,7 +1631,7 @@ void manager_send_unit_plymouth(Manager *m, Unit *u) { } if (asprintf(&message, "U\002%c%s%n", (int) (strlen(u->id) + 1), u->id, &n) < 0) { - log_error("Out of memory"); + log_oom(); goto finish; } @@ -1731,7 +1728,7 @@ int manager_open_serialization(Manager *m, FILE **_f) { return 0; } -int manager_serialize(Manager *m, FILE *f, FDSet *fds) { +int manager_serialize(Manager *m, FILE *f, FDSet *fds, bool serialize_jobs) { Iterator i; Unit *u; const char *t; @@ -1745,11 +1742,16 @@ int manager_serialize(Manager *m, FILE *f, FDSet *fds) { fprintf(f, "current-job-id=%i\n", m->current_job_id); fprintf(f, "taint-usr=%s\n", yes_no(m->taint_usr)); + fprintf(f, "n-installed-jobs=%u\n", m->n_installed_jobs); + fprintf(f, "n-failed-jobs=%u\n", m->n_failed_jobs); + dual_timestamp_serialize(f, "firmware-timestamp", &m->firmware_timestamp); + dual_timestamp_serialize(f, "kernel-timestamp", &m->kernel_timestamp); + dual_timestamp_serialize(f, "loader-timestamp", &m->loader_timestamp); dual_timestamp_serialize(f, "initrd-timestamp", &m->initrd_timestamp); - if (! in_initrd()) { - dual_timestamp_serialize(f, "startup-timestamp", &m->startup_timestamp); + if (!in_initrd()) { + dual_timestamp_serialize(f, "userspace-timestamp", &m->userspace_timestamp); dual_timestamp_serialize(f, "finish-timestamp", &m->finish_timestamp); } @@ -1766,7 +1768,7 @@ int manager_serialize(Manager *m, FILE *f, FDSet *fds) { fputs(u->id, f); fputc('\n', f); - if ((r = unit_serialize(u, f, fds)) < 0) { + if ((r = unit_serialize(u, f, fds, serialize_jobs)) < 0) { m->n_reloading --; return r; } @@ -1820,6 +1822,20 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) { log_debug("Failed to parse current job id value %s", l+15); else m->current_job_id = MAX(m->current_job_id, id); + } else if (startswith(l, "n-installed-jobs=")) { + uint32_t n; + + if (safe_atou32(l+17, &n) < 0) + log_debug("Failed to parse installed jobs counter %s", l+17); + else + m->n_installed_jobs += n; + } else if (startswith(l, "n-failed-jobs=")) { + uint32_t n; + + if (safe_atou32(l+14, &n) < 0) + log_debug("Failed to parse failed jobs counter %s", l+14); + else + m->n_failed_jobs += n; } else if (startswith(l, "taint-usr=")) { int b; @@ -1827,10 +1843,16 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) { log_debug("Failed to parse taint /usr flag %s", l+10); else m->taint_usr = m->taint_usr || b; - } else if (startswith(l, "initrd-timestamp=")) + } else if (startswith(l, "firmware-timestamp=")) + dual_timestamp_deserialize(l+19, &m->firmware_timestamp); + else if (startswith(l, "loader-timestamp=")) + dual_timestamp_deserialize(l+17, &m->loader_timestamp); + else if (startswith(l, "kernel-timestamp=")) + dual_timestamp_deserialize(l+17, &m->kernel_timestamp); + else if (startswith(l, "initrd-timestamp=")) dual_timestamp_deserialize(l+17, &m->initrd_timestamp); - else if (startswith(l, "startup-timestamp=")) - dual_timestamp_deserialize(l+18, &m->startup_timestamp); + else if (startswith(l, "userspace-timestamp=")) + dual_timestamp_deserialize(l+20, &m->userspace_timestamp); else if (startswith(l, "finish-timestamp=")) dual_timestamp_deserialize(l+17, &m->finish_timestamp); else @@ -1892,7 +1914,7 @@ int manager_reload(Manager *m) { goto finish; } - r = manager_serialize(m, f, fds); + r = manager_serialize(m, f, fds, true); if (r < 0) { m->n_reloading --; goto finish; @@ -1995,7 +2017,7 @@ bool manager_unit_pending_inactive(Manager *m, const char *name) { void manager_check_finished(Manager *m) { char userspace[FORMAT_TIMESPAN_MAX], initrd[FORMAT_TIMESPAN_MAX], kernel[FORMAT_TIMESPAN_MAX], sum[FORMAT_TIMESPAN_MAX]; - usec_t kernel_usec, initrd_usec, userspace_usec, total_usec; + usec_t firmware_usec, loader_usec, kernel_usec, initrd_usec, userspace_usec, total_usec; assert(m); @@ -2005,6 +2027,9 @@ void manager_check_finished(Manager *m) { /* Notify Type=idle units that we are done now */ close_pipe(m->idle_pipe); + /* Turn off confirm spawn now */ + m->confirm_spawn = false; + if (dual_timestamp_is_set(&m->finish_timestamp)) return; @@ -2012,37 +2037,62 @@ void manager_check_finished(Manager *m) { if (m->running_as == MANAGER_SYSTEM && detect_container(NULL) <= 0) { - userspace_usec = m->finish_timestamp.monotonic - m->startup_timestamp.monotonic; - total_usec = m->finish_timestamp.monotonic; + /* Note that m->kernel_usec.monotonic is always at 0, + * and m->firmware_usec.monotonic and + * m->loader_usec.monotonic should be considered + * negative values. */ - if (dual_timestamp_is_set(&m->initrd_timestamp)) { + firmware_usec = m->firmware_timestamp.monotonic - m->loader_timestamp.monotonic; + loader_usec = m->loader_timestamp.monotonic - m->kernel_timestamp.monotonic; + userspace_usec = m->finish_timestamp.monotonic - m->userspace_timestamp.monotonic; + total_usec = m->firmware_timestamp.monotonic + m->finish_timestamp.monotonic; - kernel_usec = m->initrd_timestamp.monotonic; - initrd_usec = m->startup_timestamp.monotonic - m->initrd_timestamp.monotonic; + if (dual_timestamp_is_set(&m->initrd_timestamp)) { - log_info("Startup finished in %s (kernel) + %s (initrd) + %s (userspace) = %s.", - format_timespan(kernel, sizeof(kernel), kernel_usec), - format_timespan(initrd, sizeof(initrd), initrd_usec), - format_timespan(userspace, sizeof(userspace), userspace_usec), - format_timespan(sum, sizeof(sum), total_usec)); + kernel_usec = m->initrd_timestamp.monotonic - m->kernel_timestamp.monotonic; + initrd_usec = m->userspace_timestamp.monotonic - m->initrd_timestamp.monotonic; + + if (!log_on_console()) + log_struct(LOG_INFO, + "MESSAGE_ID=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(SD_MESSAGE_STARTUP_FINISHED), + "KERNEL_USEC=%llu", (unsigned long long) kernel_usec, + "INITRD_USEC=%llu", (unsigned long long) initrd_usec, + "USERSPACE_USEC=%llu", (unsigned long long) userspace_usec, + "MESSAGE=Startup finished in %s (kernel) + %s (initrd) + %s (userspace) = %s.", + format_timespan(kernel, sizeof(kernel), kernel_usec), + format_timespan(initrd, sizeof(initrd), initrd_usec), + format_timespan(userspace, sizeof(userspace), userspace_usec), + format_timespan(sum, sizeof(sum), total_usec), + NULL); } else { - kernel_usec = m->startup_timestamp.monotonic; + kernel_usec = m->userspace_timestamp.monotonic - m->kernel_timestamp.monotonic; initrd_usec = 0; - log_info("Startup finished in %s (kernel) + %s (userspace) = %s.", - format_timespan(kernel, sizeof(kernel), kernel_usec), - format_timespan(userspace, sizeof(userspace), userspace_usec), - format_timespan(sum, sizeof(sum), total_usec)); + if (!log_on_console()) + log_struct(LOG_INFO, + "MESSAGE_ID=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(SD_MESSAGE_STARTUP_FINISHED), + "KERNEL_USEC=%llu", (unsigned long long) kernel_usec, + "USERSPACE_USEC=%llu", (unsigned long long) userspace_usec, + "MESSAGE=Startup finished in %s (kernel) + %s (userspace) = %s.", + format_timespan(kernel, sizeof(kernel), kernel_usec), + format_timespan(userspace, sizeof(userspace), userspace_usec), + format_timespan(sum, sizeof(sum), total_usec), + NULL); } } else { - userspace_usec = initrd_usec = kernel_usec = 0; - total_usec = m->finish_timestamp.monotonic - m->startup_timestamp.monotonic; - - log_debug("Startup finished in %s.", - format_timespan(sum, sizeof(sum), total_usec)); + firmware_usec = loader_usec = initrd_usec = kernel_usec = 0; + total_usec = userspace_usec = m->finish_timestamp.monotonic - m->userspace_timestamp.monotonic; + + if (!log_on_console()) + log_struct(LOG_INFO, + "MESSAGE_ID=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(SD_MESSAGE_STARTUP_FINISHED), + "USERSPACE_USEC=%llu", (unsigned long long) userspace_usec, + "MESSAGE=Startup finished in %s.", + format_timespan(sum, sizeof(sum), total_usec), + NULL); } - bus_broadcast_finished(m, kernel_usec, initrd_usec, userspace_usec, total_usec); + bus_broadcast_finished(m, firmware_usec, loader_usec, kernel_usec, initrd_usec, userspace_usec, total_usec); sd_notifyf(false, "READY=1\nSTATUS=Startup finished in %s.", @@ -2063,23 +2113,19 @@ static int create_generator_dir(Manager *m, char **generator, const char *name) if (m->running_as == MANAGER_SYSTEM && getpid() == 1) { p = strappend("/run/systemd/", name); - if (!p) { - log_error("Out of memory"); - return -ENOMEM; - } + if (!p) + return log_oom(); - r = mkdir_p(p, 0755); + r = mkdir_p_label(p, 0755); if (r < 0) { log_error("Failed to create generator directory: %s", strerror(-r)); free(p); return r; } } else { - p = join("/tmp/systemd-", name, ".XXXXXX", NULL); - if (!p) { - log_error("Out of memory"); - return -ENOMEM; - } + p = strjoin("/tmp/systemd-", name, ".XXXXXX", NULL); + if (!p) + return log_oom(); if (!mkdtemp(p)) { free(p);