From 2f8c48b6059b9d22ff40bc260bfb1939419b4e84 Mon Sep 17 00:00:00 2001 From: Anita Zhang Date: Wed, 11 Dec 2019 21:15:42 -0800 Subject: [PATCH] core,journal: export user units' InvocationID and use as _SYSTEMD_INVOCATION_ID Write a user unit's invocation ID to /run/user//systemd/units/ similar to how a system unit's invocation ID is written to /run/systemd/units/. This lets the journal read and add a user unit's invocation ID to the _SYSTEMD_INVOCATION_ID field of logs instead of the user manager's invocation ID. Fixes #12474 --- src/core/manager.c | 13 +++++++-- src/core/unit.c | 53 ++++++++++++++++++++++++++-------- src/journal/journald-context.c | 18 +++++++++--- 3 files changed, 66 insertions(+), 18 deletions(-) diff --git a/src/core/manager.c b/src/core/manager.c index 13a6b49a8f2..171ff04631e 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -881,8 +881,17 @@ int manager_new(UnitFileScope scope, ManagerTestRunFlags test_run_flags, Manager return r; } - if (MANAGER_IS_SYSTEM(m) && test_run_flags == 0) { - r = mkdir_label("/run/systemd/units", 0755); + if (test_run_flags == 0) { + if (MANAGER_IS_SYSTEM(m)) + r = mkdir_label("/run/systemd/units", 0755); + else { + _cleanup_free_ char *units_path = NULL; + r = xdg_user_runtime_dir(&units_path, "/systemd/units"); + if (r < 0) + return r; + r = mkdir_p_label(units_path, 0755); + } + if (r < 0 && r != -EEXIST) return r; } diff --git a/src/core/unit.c b/src/core/unit.c index c406bb7ab29..03b4b57273a 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -5373,8 +5373,32 @@ void unit_remove_dependencies(Unit *u, UnitDependencyMask mask) { } } +static int unit_get_invocation_path(Unit *u, char **ret) { + char *p; + int r; + + assert(u); + assert(ret); + + if (MANAGER_IS_SYSTEM(u->manager)) + p = strjoin("/run/systemd/units/invocation:", u->id); + else { + _cleanup_free_ char *user_path = NULL; + r = xdg_user_runtime_dir(&user_path, "/systemd/units/invocation:"); + if (r < 0) + return r; + p = strjoin(user_path, u->id); + } + + if (!p) + return -ENOMEM; + + *ret = p; + return 0; +} + static int unit_export_invocation_id(Unit *u) { - const char *p; + _cleanup_free_ char *p = NULL; int r; assert(u); @@ -5385,7 +5409,10 @@ static int unit_export_invocation_id(Unit *u) { if (sd_id128_is_null(u->invocation_id)) return 0; - p = strjoina("/run/systemd/units/invocation:", u->id); + r = unit_get_invocation_path(u, &p); + if (r < 0) + return log_unit_debug_errno(u, r, "Failed to get invocation path: %m"); + r = symlink_atomic(u->invocation_id_string, p); if (r < 0) return log_unit_debug_errno(u, r, "Failed to create invocation ID symlink %s: %m", p); @@ -5538,9 +5565,6 @@ void unit_export_state_files(Unit *u) { if (!u->id) return; - if (!MANAGER_IS_SYSTEM(u->manager)) - return; - if (MANAGER_IS_TEST_RUN(u->manager)) return; @@ -5559,6 +5583,9 @@ void unit_export_state_files(Unit *u) { (void) unit_export_invocation_id(u); + if (!MANAGER_IS_SYSTEM(u->manager)) + return; + c = unit_get_exec_context(u); if (c) { (void) unit_export_log_level_max(u, c); @@ -5576,18 +5603,20 @@ void unit_unlink_state_files(Unit *u) { if (!u->id) return; - if (!MANAGER_IS_SYSTEM(u->manager)) - return; - /* Undoes the effect of unit_export_state() */ if (u->exported_invocation_id) { - p = strjoina("/run/systemd/units/invocation:", u->id); - (void) unlink(p); - - u->exported_invocation_id = false; + _cleanup_free_ char *invocation_path = NULL; + int r = unit_get_invocation_path(u, &invocation_path); + if (r >= 0) { + (void) unlink(invocation_path); + u->exported_invocation_id = false; + } } + if (!MANAGER_IS_SYSTEM(u->manager)) + return; + if (u->exported_log_level_max) { p = strjoina("/run/systemd/units/log-level-max:", u->id); (void) unlink(p); diff --git a/src/journal/journald-context.c b/src/journal/journald-context.c index 342ed062d46..cd4cfbee48c 100644 --- a/src/journal/journald-context.c +++ b/src/journal/journald-context.c @@ -325,19 +325,29 @@ static int client_context_read_invocation_id( Server *s, ClientContext *c) { - _cleanup_free_ char *value = NULL; - const char *p; + _cleanup_free_ char *p = NULL, *value = NULL; int r; assert(s); assert(c); - /* Read the invocation ID of a unit off a unit. PID 1 stores it in a per-unit symlink in /run/systemd/units/ */ + /* Read the invocation ID of a unit off a unit. + * PID 1 stores it in a per-unit symlink in /run/systemd/units/ + * User managers store it in a per-unit symlink under /run/user//systemd/units/ */ if (!c->unit) return 0; - p = strjoina("/run/systemd/units/invocation:", c->unit); + if (c->user_unit) { + r = asprintf(&p, "/run/user/" UID_FMT "/systemd/units/invocation:%s", c->owner_uid, c->user_unit); + if (r < 0) + return r; + } else { + p = strjoin("/run/systemd/units/invocation:", c->unit); + if (!p) + return -ENOMEM; + } + r = readlink_malloc(p, &value); if (r < 0) return r;