diff --git a/Avoid-tmp-being-mounted-as-tmpfs-without-the-user-s-.patch b/Avoid-tmp-being-mounted-as-tmpfs-without-the-user-s-.patch new file mode 100644 index 0000000000000000000000000000000000000000..63d6d3d35ff48f26a631deb7474e97c610ab5f3a --- /dev/null +++ b/Avoid-tmp-being-mounted-as-tmpfs-without-the-user-s-.patch @@ -0,0 +1,43 @@ +From f58c5ced373c2532b5cc44ba2e0c3a28b41472f2 Mon Sep 17 00:00:00 2001 +From: Jan Synacek +Date: Tue, 15 May 2018 09:24:20 +0200 +Subject: [PATCH] Avoid /tmp being mounted as tmpfs without the user's + will + +Ensure PrivateTmp doesn't require tmpfs through tmp.mount, but rather +adds an After relationship. + +Resolves: #1578772 + +--- + src/core/unit.c | 13 +++++++------ + 1 file changed, 7 insertions(+), 6 deletions(-) + +diff --git a/src/core/unit.c b/src/core/unit.c +index 10e314f..bb4836a 100644 +--- a/src/core/unit.c ++++ b/src/core/unit.c +@@ -1036,13 +1036,14 @@ int unit_add_exec_dependencies(Unit *u, ExecContext *c) { + return 0; + + if (c->private_tmp) { +- const char *p; + +- FOREACH_STRING(p, "/tmp", "/var/tmp") { +- r = unit_require_mounts_for(u, p, UNIT_DEPENDENCY_FILE); +- if (r < 0) +- return r; +- } ++ r = unit_add_dependency_by_name(u, UNIT_AFTER, "tmp.mount", true, UNIT_DEPENDENCY_FILE); ++ if (r < 0) ++ return r; ++ ++ r = unit_require_mounts_for(u, "/var/tmp", UNIT_DEPENDENCY_FILE); ++ if (r < 0) ++ return r; + + r = unit_add_dependency_by_name(u, UNIT_AFTER, SPECIAL_TMPFILES_SETUP_SERVICE, true, UNIT_DEPENDENCY_FILE); + if (r < 0) +-- +2.19.1 + diff --git a/Make-systemd-udevd.service-start-after-systemd-remou.patch b/Make-systemd-udevd.service-start-after-systemd-remou.patch new file mode 100644 index 0000000000000000000000000000000000000000..d4dd22d652b92b06f08098a7628c7bab9eacbc5f --- /dev/null +++ b/Make-systemd-udevd.service-start-after-systemd-remou.patch @@ -0,0 +1,25 @@ +From 4c230d1d73e9f9a6d1fe654599a63881c344a00c Mon Sep 17 00:00:00 2001 +From: openEuler Buildteam +Date: Tue, 29 Jan 2019 22:54:34 -0500 +Subject: [PATCH] Make systemd-udevd.service start after systemd-remount-fs.service. + +--- + units/systemd-udevd.service.in | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/units/systemd-udevd.service.in b/units/systemd-udevd.service.in +index 6a3814e..3b09923 100644 +--- a/units/systemd-udevd.service.in ++++ b/units/systemd-udevd.service.in +@@ -11,7 +11,7 @@ + Description=udev Kernel Device Manager + Documentation=man:systemd-udevd.service(8) man:udev(7) + DefaultDependencies=no +-After=systemd-sysusers.service systemd-hwdb-update.service ++After=systemd-sysusers.service systemd-hwdb-update.service systemd-remount-fs.service + Before=sysinit.target + ConditionPathIsReadWrite=/sys + +-- +1.8.3.1 + diff --git a/Revert-core-one-step-back-again-for-nspawn-we-actual.patch b/Revert-core-one-step-back-again-for-nspawn-we-actual.patch new file mode 100644 index 0000000000000000000000000000000000000000..2673f6bf9294a73f08fd63a60823c298f9d6074c --- /dev/null +++ b/Revert-core-one-step-back-again-for-nspawn-we-actual.patch @@ -0,0 +1,43 @@ +From 9d0046ceca10911361137d6496987cb15ffff132 Mon Sep 17 00:00:00 2001 +From: Lukas Nykryn +Date: Thu, 25 Jun 2015 09:20:59 +0200 +Subject: [PATCH] Revert "core: one step back again, for nspawn we + actually can't wait for cgroups running empty since systemd will get exactly + zero notifications about it" + +This reverts commit 743970d2ea6d08aa7c7bff8220f6b7702f2b1db7. + +https://bugzilla.redhat.com/show_bug.cgi?id=1141137 +https://github.com/systemd/systemd/pull/350 + +Resolves: #1703485 + +--- + src/core/unit.c | 11 +---------- + 1 file changed, 1 insertion(+), 10 deletions(-) + +diff --git a/src/core/unit.c b/src/core/unit.c +index 1cadcd4..10e314f 100644 +--- a/src/core/unit.c ++++ b/src/core/unit.c +@@ -4799,16 +4799,7 @@ int unit_kill_context( + + } else if (r > 0) { + +- /* FIXME: For now, on the legacy hierarchy, we will not wait for the cgroup members to die if +- * we are running in a container or if this is a delegation unit, simply because cgroup +- * notification is unreliable in these cases. It doesn't work at all in containers, and outside +- * of containers it can be confused easily by left-over directories in the cgroup — which +- * however should not exist in non-delegated units. On the unified hierarchy that's different, +- * there we get proper events. Hence rely on them. */ +- +- if (cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER) > 0 || +- (detect_container() == 0 && !unit_cgroup_delegate(u))) +- wait_for_exit = true; ++ wait_for_exit = true; + + if (send_sighup) { + set_free(pid_set); +-- +2.19.1 + diff --git a/Revert-sysctl.d-switch-net.ipv4.conf.all.rp_filter-f.patch b/Revert-sysctl.d-switch-net.ipv4.conf.all.rp_filter-f.patch new file mode 100644 index 0000000000000000000000000000000000000000..75b0f1b5341dd2899b0cee4f5678d35318826ac0 --- /dev/null +++ b/Revert-sysctl.d-switch-net.ipv4.conf.all.rp_filter-f.patch @@ -0,0 +1,29 @@ +From 47b256d63ac092137fe44e27560a14ee4aa5b7c8 Mon Sep 17 00:00:00 2001 +From: Lukas Nykryn +Date: Fri, 8 Feb 2019 10:54:34 +0100 +Subject: Revert "sysctl.d: switch net.ipv4.conf.all.rp_filter + from 1 to 2" + +This reverts commit 75c9af80cf3529c76988451e63f98010c86f48f1. + +Resolves: #1653824 +--- + sysctl.d/50-default.conf | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sysctl.d/50-default.conf b/sysctl.d/50-default.conf +index b0645f3..e263cf0 100644 +--- a/sysctl.d/50-default.conf ++++ b/sysctl.d/50-default.conf +@@ -22,7 +22,7 @@ kernel.sysrq = 16 + kernel.core_uses_pid = 1 + + # Source route verification +-net.ipv4.conf.all.rp_filter = 2 ++net.ipv4.conf.all.rp_filter = 1 + + # Do not accept source routing + net.ipv4.conf.all.accept_source_route = 0 +-- +1.8.3.1 + diff --git a/dbus-execute-avoid-extra-strdup.patch b/dbus-execute-avoid-extra-strdup.patch new file mode 100644 index 0000000000000000000000000000000000000000..3c0f80ff4640630bf3f4ae6b92dd924cb2b1ecc0 --- /dev/null +++ b/dbus-execute-avoid-extra-strdup.patch @@ -0,0 +1,41 @@ +From 66ca4903ca74604b193802635d36c48b0fcaf291 Mon Sep 17 00:00:00 2001 +From: Topi Miettinen +Date: Thu, 2 Jan 2020 19:59:48 +0200 +Subject: [PATCH] dbus-execute: avoid extra strdup() + +bind_mount_add does the strdup(), so we can avoid +strdup()ing the strings. + +https://github.com/systemd/systemd/commit/66ca4903ca74604b193802635d36c48b0fcaf291 + +--- + src/core/dbus-execute.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c +index 2be3db2..abd60ea 100644 +--- a/src/core/dbus-execute.c ++++ b/src/core/dbus-execute.c +@@ -2370,7 +2370,7 @@ int bus_exec_context_set_transient_property( + return 1; + + } else if (STR_IN_SET(name, "BindPaths", "BindReadOnlyPaths")) { +- const char *source, *destination; ++ char *source, *destination; + int ignore_enoent; + uint64_t mount_flags; + bool empty = true; +@@ -2391,8 +2391,8 @@ int bus_exec_context_set_transient_property( + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + r = bind_mount_add(&c->bind_mounts, &c->n_bind_mounts, + &(BindMount) { +- .source = strdup(source), +- .destination = strdup(destination), ++ .source = source, ++ .destination = destination, + .read_only = !!strstr(name, "ReadOnly"), + .recursive = !!(mount_flags & MS_REC), + .ignore_enoent = ignore_enoent, +-- +2.19.1 + diff --git a/fix-fd-leak-in-no-memory-condition.patch b/fix-fd-leak-in-no-memory-condition.patch new file mode 100644 index 0000000000000000000000000000000000000000..256182bc3adcb3f245c833901a7733397ad5e2cc --- /dev/null +++ b/fix-fd-leak-in-no-memory-condition.patch @@ -0,0 +1,33 @@ +From 43681c404794341a42ba0a34b9730103f4f2c560 Mon Sep 17 00:00:00 2001 +From: Gaurav +Date: Mon, 8 Apr 2019 10:13:26 +0530 +Subject: [PATCH] Fix fd leak in no memory condition + +In case of no memory situation, fd is not being close. +Please review. + +https://github.com/systemd/systemd/commit/43681c404794341a42ba0a34b9730103f4f2c560.patch + +--- + src/libsystemd/sd-event/sd-event.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c +index 5adbcee..5d0e057 100644 +--- a/src/libsystemd/sd-event/sd-event.c ++++ b/src/libsystemd/sd-event/sd-event.c +@@ -900,8 +900,10 @@ _public_ int sd_event_add_io( + assert_return(!event_pid_changed(e), -ECHILD); + + s = source_new(e, !ret, SOURCE_IO); +- if (!s) ++ if (!s) { ++ fd = safe_close(fd); + return -ENOMEM; ++ } + + s->wakeup = WAKEUP_EVENT_SOURCE; + s->io.fd = fd; +-- +2.19.1 + diff --git a/journal-don-t-enable-systemd-journald-audit.socket-b.patch b/journal-don-t-enable-systemd-journald-audit.socket-b.patch new file mode 100644 index 0000000000000000000000000000000000000000..bdb9129b23351e99f83f56d8a2383c4caec5157c --- /dev/null +++ b/journal-don-t-enable-systemd-journald-audit.socket-b.patch @@ -0,0 +1,28 @@ +From 7a650ee8d3faf79fd5ef866b69741880a3a42b8d Mon Sep 17 00:00:00 2001 +From: Jan Synacek +Date: Thu, 2 May 2019 14:11:54 +0200 +Subject: [PATCH] journal: don't enable systemd-journald-audit.socket + by default + +Resolves: #1699287 + +--- + units/systemd-journald.service.in | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/units/systemd-journald.service.in b/units/systemd-journald.service.in +index 089bc38..7436619 100644 +--- a/units/systemd-journald.service.in ++++ b/units/systemd-journald.service.in +@@ -31,7 +31,7 @@ RestrictAddressFamilies=AF_UNIX AF_NETLINK + RestrictNamespaces=yes + RestrictRealtime=yes + RestrictSUIDSGID=yes +-Sockets=systemd-journald.socket systemd-journald-dev-log.socket systemd-journald-audit.socket ++Sockets=systemd-journald.socket systemd-journald-dev-log.socket + StandardOutput=null + SystemCallArchitectures=native + SystemCallErrorNumber=EPERM +-- +2.19.1 + diff --git a/logind-set-RemoveIPC-to-false-by-default.patch b/logind-set-RemoveIPC-to-false-by-default.patch new file mode 100644 index 0000000000000000000000000000000000000000..846e34ee1e0028aadec3470466cea9f0717474e5 --- /dev/null +++ b/logind-set-RemoveIPC-to-false-by-default.patch @@ -0,0 +1,53 @@ +From 0b3833d6c3b751c6dfb40eeb2ef852984c58f546 Mon Sep 17 00:00:00 2001 +From: openEuler Buildteam +Date: Wed, 1 Aug 2018 10:58:28 +0200 +Subject: logind: set RemoveIPC to false by default + +Resolves: #1523233 +--- + man/logind.conf.xml | 2 +- + src/login/logind-core.c | 2 +- + src/login/logind.conf.in | 2 +- + 3 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/man/logind.conf.xml b/man/logind.conf.xml +index 4cbfd09..c6ff5c3 100644 +--- a/man/logind.conf.xml ++++ b/man/logind.conf.xml +@@ -327,7 +327,7 @@ + user fully logs out. Takes a boolean argument. If enabled, the user may not consume IPC resources after the + last of the user's sessions terminated. This covers System V semaphores, shared memory and message queues, as + well as POSIX shared memory and message queues. Note that IPC objects of the root user and other system users +- are excluded from the effect of this setting. Defaults to yes. ++ are excluded from the effect of this setting. Defaults to no. + + + +diff --git a/src/login/logind-core.c b/src/login/logind-core.c +index 1d21e90..2ac7860 100644 +--- a/src/login/logind-core.c ++++ b/src/login/logind-core.c +@@ -34,7 +34,7 @@ void manager_reset_config(Manager *m) { + + m->n_autovts = 6; + m->reserve_vt = 6; +- m->remove_ipc = true; ++ m->remove_ipc = false; + m->inhibit_delay_max = 5 * USEC_PER_SEC; + m->user_stop_delay = 10 * USEC_PER_SEC; + +diff --git a/src/login/logind.conf.in b/src/login/logind.conf.in +index 1029e29..c7346f9 100644 +--- a/src/login/logind.conf.in ++++ b/src/login/logind.conf.in +@@ -32,6 +32,6 @@ + #IdleAction=ignore + #IdleActionSec=30min + #RuntimeDirectorySize=10% +-#RemoveIPC=yes ++#RemoveIPC=no + #InhibitorsMax=8192 + #SessionsMax=8192 +-- +2.19.1 + diff --git a/revert-analyze-add-unit-files-to-dump-the-unit-fragm.patch b/revert-analyze-add-unit-files-to-dump-the-unit-fragm.patch new file mode 100644 index 0000000000000000000000000000000000000000..65c5162ec85b61920d291883cea7ec5ceb2960d1 --- /dev/null +++ b/revert-analyze-add-unit-files-to-dump-the-unit-fragm.patch @@ -0,0 +1,93 @@ +From e67cd21d7d174cdafd12beca4cfb6e19e61f6fb5 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Mon, 8 Jul 2019 17:33:25 +0200 +Subject: [PATCH] analyze: add "unit-files" to dump the unit fragment map + +I'm not convinced that this is useful enough to be included... But it is +certainly nice when debugging. + +revert analyze add unit files to dump the unit fragment map +--- + src/analyze/analyze.c | 50 -------------------------------------------------- + 1 file changed, 50 deletions(-) + +diff --git a/src/analyze/analyze.c b/src/analyze/analyze.c +index 322be1a..6de26f4 100644 +--- a/src/analyze/analyze.c ++++ b/src/analyze/analyze.c +@@ -1546,53 +1546,6 @@ static int get_or_set_log_target(int argc, char *argv[], void *userdata) { + return (argc == 1) ? get_log_target(argc, argv, userdata) : set_log_target(argc, argv, userdata); + } + +-static bool strv_fnmatch_strv_or_empty(char* const* patterns, char **strv, int flags) { +- char **s; +- STRV_FOREACH(s, strv) +- if (strv_fnmatch_or_empty(patterns, *s, flags)) +- return true; +- +- return false; +-} +- +-static int do_unit_files(int argc, char *argv[], void *userdata) { +- _cleanup_(lookup_paths_free) LookupPaths lp = {}; +- _cleanup_hashmap_free_ Hashmap *unit_ids = NULL; +- _cleanup_hashmap_free_ Hashmap *unit_names = NULL; +- char **patterns = strv_skip(argv, 1); +- Iterator i; +- const char *k, *dst; +- char **v; +- int r; +- +- r = lookup_paths_init(&lp, arg_scope, 0, NULL); +- if (r < 0) +- return log_error_errno(r, "lookup_paths_init() failed: %m"); +- +- r = unit_file_build_name_map(&lp, &unit_ids, &unit_names, NULL); +- if (r < 0) +- return log_error_errno(r, "unit_file_build_name_map() failed: %m"); +- +- HASHMAP_FOREACH_KEY(dst, k, unit_ids, i) { +- if (!strv_fnmatch_or_empty(patterns, k, FNM_NOESCAPE) && +- !strv_fnmatch_or_empty(patterns, dst, FNM_NOESCAPE)) +- continue; +- +- printf("ids: %s → %s\n", k, dst); +- } +- +- HASHMAP_FOREACH_KEY(v, k, unit_names, i) { +- if (!strv_fnmatch_or_empty(patterns, k, FNM_NOESCAPE) && +- !strv_fnmatch_strv_or_empty(patterns, v, FNM_NOESCAPE)) +- continue; +- +- _cleanup_free_ char *j = strv_join(v, ", "); +- printf("aliases: %s ← %s\n", k, j); +- } +- +- return 0; +-} +- + static int dump_unit_paths(int argc, char *argv[], void *userdata) { + _cleanup_(lookup_paths_free) LookupPaths paths = {}; + int r; +@@ -2263,7 +2216,6 @@ static int help(int argc, char *argv[], void *userdata) { + " log-target [TARGET] Get/set logging target for manager\n" + " dump Output state serialization of service manager\n" + " cat-config Show configuration file and drop-ins\n" +- " unit-files List files and symlinks for units\n" + " unit-paths List load directories for units\n" + " exit-status [STATUS...] List exit status definitions\n" + " syscall-filter [NAME...] Print list of syscalls in seccomp filter\n" +@@ -2467,10 +2419,8 @@ static int run(int argc, char *argv[]) { + { "get-log-level", VERB_ANY, 1, 0, get_log_level }, + { "set-log-target", 2, 2, 0, set_log_target }, + { "get-log-target", VERB_ANY, 1, 0, get_log_target }, +- + { "dump", VERB_ANY, 1, 0, dump }, + { "cat-config", 2, VERB_ANY, 0, cat_config }, +- { "unit-files", VERB_ANY, VERB_ANY, 0, do_unit_files }, + { "unit-paths", 1, 1, 0, dump_unit_paths }, + { "exit-status", VERB_ANY, VERB_ANY, 0, dump_exit_status }, + { "syscall-filter", VERB_ANY, VERB_ANY, 0, dump_syscall_filters }, +-- +1.8.3.1 + diff --git a/revert-pid1-drop-unit-caches-only-based-on-mtime.patch b/revert-pid1-drop-unit-caches-only-based-on-mtime.patch new file mode 100644 index 0000000000000000000000000000000000000000..e12236a743e689df5645a4553501162ef9fcc2c7 --- /dev/null +++ b/revert-pid1-drop-unit-caches-only-based-on-mtime.patch @@ -0,0 +1,289 @@ +From 91e0ee5f16321656ed6f827742ecbeb2b36027f2 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Wed, 10 Jul 2019 18:01:13 +0200 +Subject: [PATCH] pid1: drop unit caches only based on mtime + +v2: +- do not watch mtime of transient and generated dirs + + We'd reload the map after every transient unit we created, which we don't + need to do, since we create those units ourselves and know their fragment + path. + +revert pid1 drop unit caches only based on mtime +--- + src/analyze/analyze.c | 2 +- + src/core/load-fragment.c | 9 -------- + src/core/manager.c | 14 ++++++++++-- + src/core/manager.h | 1 - + src/shared/unit-file.c | 57 +---------------------------------------------- + src/shared/unit-file.h | 2 -- + src/systemctl/systemctl.c | 2 +- + src/test/test-unit-file.c | 13 +---------- + 8 files changed, 16 insertions(+), 84 deletions(-) + +diff --git a/src/analyze/analyze.c b/src/analyze/analyze.c +index 4d81026..322be1a 100644 +--- a/src/analyze/analyze.c ++++ b/src/analyze/analyze.c +@@ -1569,7 +1569,7 @@ static int do_unit_files(int argc, char *argv[], void *userdata) { + if (r < 0) + return log_error_errno(r, "lookup_paths_init() failed: %m"); + +- r = unit_file_build_name_map(&lp, NULL, &unit_ids, &unit_names, NULL); ++ r = unit_file_build_name_map(&lp, &unit_ids, &unit_names, NULL); + if (r < 0) + return log_error_errno(r, "unit_file_build_name_map() failed: %m"); + +diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c +index 8eaf8b3..9821a92 100644 +--- a/src/core/load-fragment.c ++++ b/src/core/load-fragment.c +@@ -4605,15 +4605,6 @@ int unit_load_fragment(Unit *u) { + return 0; + } + +- /* Possibly rebuild the fragment map to catch new units */ +- r = unit_file_build_name_map(&u->manager->lookup_paths, +- &u->manager->unit_cache_mtime, +- &u->manager->unit_id_map, +- &u->manager->unit_name_map, +- &u->manager->unit_path_cache); +- if (r < 0) +- log_error_errno(r, "Failed to rebuild name map: %m"); +- + r = unit_file_find_fragment(u->manager->unit_id_map, + u->manager->unit_name_map, + u->id, +diff --git a/src/core/manager.c b/src/core/manager.c +index 5efcf45..8b1ce70 100644 +--- a/src/core/manager.c ++++ b/src/core/manager.c +@@ -693,7 +693,6 @@ static void manager_free_unit_name_maps(Manager *m) { + m->unit_id_map = hashmap_free(m->unit_id_map); + m->unit_name_map = hashmap_free(m->unit_name_map); + m->unit_path_cache = set_free_free(m->unit_path_cache); +- m->unit_cache_mtime = 0; + } + + static int manager_setup_run_queue(Manager *m) { +@@ -1642,6 +1641,11 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds) { + + lookup_paths_log(&m->lookup_paths); + ++ manager_free_unit_name_maps(m); ++ r = unit_file_build_name_map(&m->lookup_paths, &m->unit_id_map, &m->unit_name_map, &m->unit_path_cache); ++ if (r < 0) ++ return log_error_errno(r, "Failed to build name map: %m"); ++ + { + /* This block is (optionally) done with the reloading counter bumped */ + _cleanup_(manager_reloading_stopp) Manager *reloading = NULL; +@@ -2858,6 +2862,10 @@ int manager_loop(Manager *m) { + assert(m); + assert(m->objective == MANAGER_OK); /* Ensure manager_startup() has been called */ + ++ /* Release the path and unit name caches */ ++ manager_free_unit_name_maps(m); ++ // FIXME: once this happens, we cannot load any more units ++ + manager_check_finished(m); + + /* There might still be some zombies hanging around from before we were exec()'ed. Let's reap them. */ +@@ -3531,8 +3539,10 @@ int manager_reload(Manager *m) { + + lookup_paths_log(&m->lookup_paths); + +- /* We flushed out generated files, for which we don't watch mtime, so we should flush the old map. */ + manager_free_unit_name_maps(m); ++ r = unit_file_build_name_map(&m->lookup_paths, &m->unit_id_map, &m->unit_name_map, &m->unit_path_cache); ++ if (r < 0) ++ log_warning_errno(r, "Failed to build name map: %m"); + + /* First, enumerate what we can from kernel and suchlike */ + manager_enumerate_perpetual(m); +diff --git a/src/core/manager.h b/src/core/manager.h +index 815c5ec..9ca82ac 100644 +--- a/src/core/manager.h ++++ b/src/core/manager.h +@@ -223,7 +223,6 @@ struct Manager { + Hashmap *unit_id_map; + Hashmap *unit_name_map; + Set *unit_path_cache; +- usec_t unit_cache_mtime; + + char **transient_environment; /* The environment, as determined from config files, kernel cmdline and environment generators */ + char **client_environment; /* Environment variables created by clients through the bus API */ +diff --git a/src/shared/unit-file.c b/src/shared/unit-file.c +index 4a5f23e..bad92a3 100644 +--- a/src/shared/unit-file.c ++++ b/src/shared/unit-file.c +@@ -152,47 +152,8 @@ static int unit_ids_map_get( + return -ELOOP; + } + +-static bool lookup_paths_mtime_exclude(const LookupPaths *lp, const char *path) { +- /* Paths that are under our exclusive control. Users shall not alter those directly. */ +- +- return streq_ptr(path, lp->generator) || +- streq_ptr(path, lp->generator_early) || +- streq_ptr(path, lp->generator_late) || +- streq_ptr(path, lp->transient) || +- streq_ptr(path, lp->persistent_control) || +- streq_ptr(path, lp->runtime_control); +-} +- +-static bool lookup_paths_mtime_good(const LookupPaths *lp, usec_t mtime) { +- char **dir; +- +- STRV_FOREACH(dir, (char**) lp->search_path) { +- struct stat st; +- +- if (lookup_paths_mtime_exclude(lp, *dir)) +- continue; +- +- /* Determine the latest lookup path modification time */ +- if (stat(*dir, &st) < 0) { +- if (errno == ENOENT) +- continue; +- +- log_debug_errno(errno, "Failed to stat %s, ignoring: %m", *dir); +- continue; +- } +- +- if (timespec_load(&st.st_mtim) > mtime) { +- log_debug_errno(errno, "Unit dir %s has changed, need to update cache.", *dir); +- return false; +- } +- } +- +- return true; +-} +- + int unit_file_build_name_map( + const LookupPaths *lp, +- usec_t *cache_mtime, + Hashmap **ret_unit_ids_map, + Hashmap **ret_unit_names_map, + Set **ret_path_cache) { +@@ -210,12 +171,6 @@ int unit_file_build_name_map( + _cleanup_set_free_free_ Set *paths = NULL; + char **dir; + int r; +- usec_t mtime = 0; +- +- /* Before doing anything, check if the mtime that was passed is still valid. If +- * yes, do nothing. If *cache_time == 0, always build the cache. */ +- if (cache_mtime && *cache_mtime > 0 && lookup_paths_mtime_good(lp, *cache_mtime)) +- return 0; + + if (ret_path_cache) { + paths = set_new(&path_hash_ops); +@@ -226,7 +181,6 @@ int unit_file_build_name_map( + STRV_FOREACH(dir, (char**) lp->search_path) { + struct dirent *de; + _cleanup_closedir_ DIR *d = NULL; +- struct stat st; + + d = opendir(*dir); + if (!d) { +@@ -235,13 +189,6 @@ int unit_file_build_name_map( + continue; + } + +- /* Determine the latest lookup path modification time */ +- if (fstat(dirfd(d), &st) < 0) +- return log_error_errno(errno, "Failed to fstat %s: %m", *dir); +- +- if (!lookup_paths_mtime_exclude(lp, *dir)) +- mtime = MAX(mtime, timespec_load(&st.st_mtim)); +- + FOREACH_DIRENT_ALL(de, d, log_warning_errno(errno, "Failed to read \"%s\", ignoring: %m", *dir)) { + char *filename; + _cleanup_free_ char *_filename_free = NULL, *simplified = NULL; +@@ -378,14 +325,12 @@ int unit_file_build_name_map( + basename(dst), src); + } + +- if (cache_mtime) +- *cache_mtime = mtime; + *ret_unit_ids_map = TAKE_PTR(ids); + *ret_unit_names_map = TAKE_PTR(names); + if (ret_path_cache) + *ret_path_cache = TAKE_PTR(paths); + +- return 1; ++ return 0; + } + + int unit_file_find_fragment( +diff --git a/src/shared/unit-file.h b/src/shared/unit-file.h +index 54cc787..52e17f7 100644 +--- a/src/shared/unit-file.h ++++ b/src/shared/unit-file.h +@@ -4,7 +4,6 @@ + #include + + #include "hashmap.h" +-#include "time-util.h" + #include "unit-name.h" + + typedef enum UnitFileState UnitFileState; +@@ -43,7 +42,6 @@ int unit_validate_alias_symlink_and_warn(const char *filename, const char *targe + + int unit_file_build_name_map( + const LookupPaths *lp, +- usec_t *ret_time, + Hashmap **ret_unit_ids_map, + Hashmap **ret_unit_names_map, + Set **ret_path_cache); +diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c +index dcf76be..69063ee 100644 +--- a/src/systemctl/systemctl.c ++++ b/src/systemctl/systemctl.c +@@ -2594,7 +2594,7 @@ static int unit_find_paths( + _cleanup_set_free_free_ Set *names = NULL; + + if (!cached_name_map) { +- r = unit_file_build_name_map(lp, NULL, &cached_id_map, &cached_name_map, NULL); ++ r = unit_file_build_name_map(lp, &cached_id_map, &cached_name_map, NULL); + if (r < 0) + return r; + } +diff --git a/src/test/test-unit-file.c b/src/test/test-unit-file.c +index 8bc5bf6..988ac15 100644 +--- a/src/test/test-unit-file.c ++++ b/src/test/test-unit-file.c +@@ -32,12 +32,10 @@ static void test_unit_file_build_name_map(char **ids) { + Iterator i; + const char *k, *dst; + char **v; +- usec_t mtime = 0; +- int r; + + assert_se(lookup_paths_init(&lp, UNIT_FILE_SYSTEM, 0, NULL) >= 0); + +- assert_se(unit_file_build_name_map(&lp, &mtime, &unit_ids, &unit_names, NULL) == 1); ++ assert_se(unit_file_build_name_map(&lp, &unit_ids, &unit_names, NULL) == 0); + + HASHMAP_FOREACH_KEY(dst, k, unit_ids, i) + log_info("ids: %s → %s", k, dst); +@@ -47,15 +45,6 @@ static void test_unit_file_build_name_map(char **ids) { + log_info("aliases: %s ← %s", k, j); + } + +- char buf[FORMAT_TIMESTAMP_MAX]; +- log_debug("Last modification time: %s", format_timestamp(buf, sizeof buf, mtime)); +- +- r = unit_file_build_name_map(&lp, &mtime, &unit_ids, &unit_names, NULL); +- assert_se(IN_SET(r, 0, 1)); +- if (r == 0) +- log_debug("Cache rebuild skipped based on mtime."); +- +- + char **id; + STRV_FOREACH(id, ids) { + const char *fragment, *name; +-- +1.8.3.1 + diff --git a/revert-pid1-use-a-cache-for-all-unit-aliases.patch b/revert-pid1-use-a-cache-for-all-unit-aliases.patch new file mode 100644 index 0000000000000000000000000000000000000000..7dc96a5a6b40b7830b81934adaa078c508b062b0 --- /dev/null +++ b/revert-pid1-use-a-cache-for-all-unit-aliases.patch @@ -0,0 +1,1226 @@ +From e8630e695232bdfcd16b55f3faafb4329c961104 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Thu, 18 Jul 2019 13:11:28 +0200 +Subject: [PATCH] pid1: use a cache for all unit aliases + +This reworks how we load units from disk. Instead of chasing symlinks every +time we are asked to load a unit by name, we slurp all symlinks from disk +and build two hashmaps: +1. from unit name to either alias target, or fragment on disk + (if an alias, we put just the target name in the hashmap, if a fragment + we put an absolute path, so we can distinguish both). +2. from a unit name to all aliases + +Reading all this data can be pretty costly (40 ms) on my machine, so we keep it +around for reuse. + +The advantage is that we can reliably know what all the aliases of a given unit +are. This means we can reliably load dropins under all names. This fixes #11972. + +revert pid1 use a cache for all unit aliases +--- + src/core/load-fragment.c | 350 +++++++++++++++++++++++++++-------- + src/core/manager.c | 73 ++++++-- + src/core/manager.h | 2 - + src/core/unit.c | 3 - + src/shared/unit-file.c | 362 ------------------------------------- + src/shared/unit-file.h | 15 -- + src/systemctl/systemctl.c | 47 +++-- + src/test/test-unit-file.c | 40 ---- + test/TEST-15-DROPIN/test-dropin.sh | 33 ++-- + 9 files changed, 378 insertions(+), 547 deletions(-) + +diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c +index 9821a92..9dd86e8 100644 +--- a/src/core/load-fragment.c ++++ b/src/core/load-fragment.c +@@ -4553,48 +4553,251 @@ int config_parse_ip_filter_bpf_progs( + return 0; + } + ++#define FOLLOW_MAX 8 ++ ++static int open_follow(char **filename, FILE **_f, Set *names, char **_final) { ++ char *id = NULL; ++ unsigned c = 0; ++ int fd, r; ++ FILE *f; ++ ++ assert(filename); ++ assert(*filename); ++ assert(_f); ++ assert(names); ++ ++ /* This will update the filename pointer if the loaded file is ++ * reached by a symlink. The old string will be freed. */ ++ ++ for (;;) { ++ char *target, *name; ++ ++ if (c++ >= FOLLOW_MAX) ++ return -ELOOP; ++ ++ path_simplify(*filename, false); ++ ++ /* Add the file name we are currently looking at to ++ * the names of this unit, but only if it is a valid ++ * unit name. */ ++ name = basename(*filename); ++ if (unit_name_is_valid(name, UNIT_NAME_ANY)) { ++ ++ id = set_get(names, name); ++ if (!id) { ++ id = strdup(name); ++ if (!id) ++ return -ENOMEM; ++ ++ r = set_consume(names, id); ++ if (r < 0) ++ return r; ++ } ++ } ++ ++ /* Try to open the file name, but don't if its a symlink */ ++ fd = open(*filename, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW); ++ if (fd >= 0) ++ break; ++ ++ if (errno != ELOOP) ++ return -errno; ++ ++ /* Hmm, so this is a symlink. Let's read the name, and follow it manually */ ++ r = readlink_and_make_absolute(*filename, &target); ++ if (r < 0) ++ return r; ++ ++ free_and_replace(*filename, target); ++ } ++ ++ f = fdopen(fd, "r"); ++ if (!f) { ++ safe_close(fd); ++ return -errno; ++ } ++ ++ *_f = f; ++ *_final = id; ++ ++ return 0; ++} ++ + static int merge_by_names(Unit **u, Set *names, const char *id) { + char *k; + int r; + + assert(u); + assert(*u); ++ assert(names); + +- /* Let's try to add in all names that are aliases of this unit */ ++ /* Let's try to add in all symlink names we found */ + while ((k = set_steal_first(names))) { +- _cleanup_free_ _unused_ char *free_k = k; + +- /* First try to merge in the other name into our unit */ ++ /* First try to merge in the other name into our ++ * unit */ + r = unit_merge_by_name(*u, k); + if (r < 0) { + Unit *other; + +- /* Hmm, we couldn't merge the other unit into ours? Then let's try it the other way +- * round. */ ++ /* Hmm, we couldn't merge the other unit into ++ * ours? Then let's try it the other way ++ * round */ + +- other = manager_get_unit((*u)->manager, k); +- if (!other) +- return r; /* return previous failure */ ++ /* If the symlink name we are looking at is unit template, then ++ we must search for instance of this template */ ++ if (unit_name_is_valid(k, UNIT_NAME_TEMPLATE) && (*u)->instance) { ++ _cleanup_free_ char *instance = NULL; + +- r = unit_merge(other, *u); +- if (r < 0) +- return r; ++ r = unit_name_replace_instance(k, (*u)->instance, &instance); ++ if (r < 0) ++ return r; + +- *u = other; +- return merge_by_names(u, names, NULL); ++ other = manager_get_unit((*u)->manager, instance); ++ } else ++ other = manager_get_unit((*u)->manager, k); ++ ++ free(k); ++ ++ if (other) { ++ r = unit_merge(other, *u); ++ if (r >= 0) { ++ *u = other; ++ return merge_by_names(u, names, NULL); ++ } ++ } ++ ++ return r; + } + +- if (streq_ptr(id, k)) ++ if (id == k) + unit_choose_id(*u, id); ++ ++ free(k); ++ } ++ ++ return 0; ++} ++ ++static int load_from_path(Unit *u, const char *path) { ++ _cleanup_set_free_free_ Set *symlink_names = NULL; ++ _cleanup_fclose_ FILE *f = NULL; ++ _cleanup_free_ char *filename = NULL; ++ char *id = NULL; ++ Unit *merged; ++ struct stat st; ++ int r; ++ ++ assert(u); ++ assert(path); ++ ++ symlink_names = set_new(&string_hash_ops); ++ if (!symlink_names) ++ return -ENOMEM; ++ ++ if (path_is_absolute(path)) { ++ ++ filename = strdup(path); ++ if (!filename) ++ return -ENOMEM; ++ ++ r = open_follow(&filename, &f, symlink_names, &id); ++ if (r < 0) { ++ filename = mfree(filename); ++ if (r != -ENOENT) ++ return r; ++ } ++ ++ } else { ++ char **p; ++ ++ STRV_FOREACH(p, u->manager->lookup_paths.search_path) { ++ ++ /* Instead of opening the path right away, we manually ++ * follow all symlinks and add their name to our unit ++ * name set while doing so */ ++ filename = path_make_absolute(path, *p); ++ if (!filename) ++ return -ENOMEM; ++ ++ if (u->manager->unit_path_cache && ++ !set_get(u->manager->unit_path_cache, filename)) ++ r = -ENOENT; ++ else ++ r = open_follow(&filename, &f, symlink_names, &id); ++ if (r >= 0) ++ break; ++ ++ /* ENOENT means that the file is missing or is a dangling symlink. ++ * ENOTDIR means that one of paths we expect to be is a directory ++ * is not a directory, we should just ignore that. ++ * EACCES means that the directory or file permissions are wrong. ++ */ ++ if (r == -EACCES) ++ log_debug_errno(r, "Cannot access \"%s\": %m", filename); ++ else if (!IN_SET(r, -ENOENT, -ENOTDIR)) ++ return r; ++ ++ filename = mfree(filename); ++ /* Empty the symlink names for the next run */ ++ set_clear_free(symlink_names); ++ } ++ } ++ ++ if (!filename) ++ /* Hmm, no suitable file found? */ ++ return 0; ++ ++ if (!unit_type_may_alias(u->type) && set_size(symlink_names) > 1) { ++ log_unit_warning(u, "Unit type of %s does not support alias names, refusing loading via symlink.", u->id); ++ return -ELOOP; ++ } ++ ++ merged = u; ++ r = merge_by_names(&merged, symlink_names, id); ++ if (r < 0) ++ return r; ++ ++ if (merged != u) { ++ u->load_state = UNIT_MERGED; ++ return 0; ++ } ++ ++ if (fstat(fileno(f), &st) < 0) ++ return -errno; ++ ++ if (null_or_empty(&st)) { ++ u->load_state = UNIT_MASKED; ++ u->fragment_mtime = 0; ++ } else { ++ u->load_state = UNIT_LOADED; ++ u->fragment_mtime = timespec_load(&st.st_mtim); ++ ++ /* Now, parse the file contents */ ++ r = config_parse(u->id, filename, f, ++ UNIT_VTABLE(u)->sections, ++ config_item_perf_lookup, load_fragment_gperf_lookup, ++ CONFIG_PARSE_ALLOW_INCLUDE, u); ++ if (r < 0) ++ return r; ++ } ++ ++ free_and_replace(u->fragment_path, filename); ++ ++ if (u->source_path) { ++ if (stat(u->source_path, &st) >= 0) ++ u->source_mtime = timespec_load(&st.st_mtim); ++ else ++ u->source_mtime = 0; + } + + return 0; + } + + int unit_load_fragment(Unit *u) { +- const char *fragment; +- _cleanup_set_free_free_ Set *names = NULL; + int r; ++ Iterator i; ++ const char *t; + + assert(u); + assert(u->load_state == UNIT_STUB); +@@ -4605,79 +4808,78 @@ int unit_load_fragment(Unit *u) { + return 0; + } + +- r = unit_file_find_fragment(u->manager->unit_id_map, +- u->manager->unit_name_map, +- u->id, +- &fragment, +- &names); +- if (r < 0 && r != -ENOENT) ++ /* First, try to find the unit under its id. We always look ++ * for unit files in the default directories, to make it easy ++ * to override things by placing things in /etc/systemd/system */ ++ r = load_from_path(u, u->id); ++ if (r < 0) + return r; + +- if (fragment) { +- /* Open the file, check if this is a mask, otherwise read. */ +- _cleanup_fclose_ FILE *f = NULL; +- struct stat st; ++ /* Try to find an alias we can load this with */ ++ if (u->load_state == UNIT_STUB) { ++ SET_FOREACH(t, u->names, i) { + +- /* Try to open the file name. A symlink is OK, for example for linked files or masks. We +- * expect that all symlinks within the lookup paths have been already resolved, but we don't +- * verify this here. */ +- f = fopen(fragment, "re"); +- if (!f) +- return log_unit_notice_errno(u, errno, "Failed to open %s: %m", fragment); ++ if (t == u->id) ++ continue; + +- if (fstat(fileno(f), &st) < 0) +- return -errno; ++ r = load_from_path(u, t); ++ if (r < 0) ++ return r; + +- r = free_and_strdup(&u->fragment_path, fragment); ++ if (u->load_state != UNIT_STUB) ++ break; ++ } ++ } ++ ++ /* And now, try looking for it under the suggested (originally linked) path */ ++ if (u->load_state == UNIT_STUB && u->fragment_path) { ++ ++ r = load_from_path(u, u->fragment_path); + if (r < 0) + return r; + +- if (null_or_empty(&st)) { +- u->load_state = UNIT_MASKED; +- u->fragment_mtime = 0; +- } else { +- u->load_state = UNIT_LOADED; +- u->fragment_mtime = timespec_load(&st.st_mtim); +- +- /* Now, parse the file contents */ +- r = config_parse(u->id, fragment, f, +- UNIT_VTABLE(u)->sections, +- config_item_perf_lookup, load_fragment_gperf_lookup, +- CONFIG_PARSE_ALLOW_INCLUDE, u); +- if (r == -ENOEXEC) +- log_unit_notice_errno(u, r, "Unit configuration has fatal error, unit will not be started."); +- if (r < 0) +- return r; +- } ++ if (u->load_state == UNIT_STUB) ++ /* Hmm, this didn't work? Then let's get rid ++ * of the fragment path stored for us, so that ++ * we don't point to an invalid location. */ ++ u->fragment_path = mfree(u->fragment_path); + } + +- /* We do the merge dance here because for some unit types, the unit might have aliases which are not +- * declared in the file system. In particular, this is true (and frequent) for device and swap units. +- */ +- Unit *merged; +- const char *id = u->id; +- _cleanup_free_ char *free_id = NULL; ++ /* Look for a template */ ++ if (u->load_state == UNIT_STUB && u->instance) { ++ _cleanup_free_ char *k = NULL; + +- if (fragment) { +- id = basename(fragment); +- if (unit_name_is_valid(id, UNIT_NAME_TEMPLATE)) { +- assert(u->instance); /* If we're not trying to use a template for non-instanced unit, +- * this must be set. */ ++ r = unit_name_template(u->id, &k); ++ if (r < 0) ++ return r; + +- r = unit_name_replace_instance(id, u->instance, &free_id); +- if (r < 0) +- return log_debug_errno(r, "Failed to build id (%s + %s): %m", id, u->instance); +- id = free_id; ++ r = load_from_path(u, k); ++ if (r < 0) { ++ if (r == -ENOEXEC) ++ log_unit_notice(u, "Unit configuration has fatal error, unit will not be started."); ++ return r; + } +- } + +- merged = u; +- r = merge_by_names(&merged, names, id); +- if (r < 0) +- return r; ++ if (u->load_state == UNIT_STUB) { ++ SET_FOREACH(t, u->names, i) { ++ _cleanup_free_ char *z = NULL; + +- if (merged != u) +- u->load_state = UNIT_MERGED; ++ if (t == u->id) ++ continue; ++ ++ r = unit_name_template(t, &z); ++ if (r < 0) ++ return r; ++ ++ r = load_from_path(u, z); ++ if (r < 0) ++ return r; ++ ++ if (u->load_state != UNIT_STUB) ++ break; ++ } ++ } ++ } + + return 0; + } +diff --git a/src/core/manager.c b/src/core/manager.c +index 8b1ce70..cfeaca6 100644 +--- a/src/core/manager.c ++++ b/src/core/manager.c +@@ -689,12 +689,6 @@ static int manager_setup_prefix(Manager *m) { + return 0; + } + +-static void manager_free_unit_name_maps(Manager *m) { +- m->unit_id_map = hashmap_free(m->unit_id_map); +- m->unit_name_map = hashmap_free(m->unit_name_map); +- m->unit_path_cache = set_free_free(m->unit_path_cache); +-} +- + static int manager_setup_run_queue(Manager *m) { + int r; + +@@ -1383,7 +1377,7 @@ Manager* manager_free(Manager *m) { + strv_free(m->client_environment); + + hashmap_free(m->cgroup_unit); +- manager_free_unit_name_maps(m); ++ set_free_free(m->unit_path_cache); + + free(m->switch_root); + free(m->switch_root_init); +@@ -1487,6 +1481,56 @@ static void manager_catchup(Manager *m) { + } + } + ++static void manager_build_unit_path_cache(Manager *m) { ++ char **i; ++ int r; ++ ++ assert(m); ++ ++ set_free_free(m->unit_path_cache); ++ ++ m->unit_path_cache = set_new(&path_hash_ops); ++ if (!m->unit_path_cache) { ++ r = -ENOMEM; ++ goto fail; ++ } ++ ++ /* This simply builds a list of files we know exist, so that ++ * we don't always have to go to disk */ ++ ++ STRV_FOREACH(i, m->lookup_paths.search_path) { ++ _cleanup_closedir_ DIR *d = NULL; ++ struct dirent *de; ++ ++ d = opendir(*i); ++ if (!d) { ++ if (errno != ENOENT) ++ log_warning_errno(errno, "Failed to open directory %s, ignoring: %m", *i); ++ continue; ++ } ++ ++ FOREACH_DIRENT(de, d, r = -errno; goto fail) { ++ char *p; ++ ++ p = path_join(*i, de->d_name); ++ if (!p) { ++ r = -ENOMEM; ++ goto fail; ++ } ++ ++ r = set_consume(m->unit_path_cache, p); ++ if (r < 0) ++ goto fail; ++ } ++ } ++ ++ return; ++ ++fail: ++ log_warning_errno(r, "Failed to build unit path cache, proceeding without: %m"); ++ m->unit_path_cache = set_free_free(m->unit_path_cache); ++} ++ + static void manager_distribute_fds(Manager *m, FDSet *fds) { + Iterator i; + Unit *u; +@@ -1641,10 +1685,7 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds) { + + lookup_paths_log(&m->lookup_paths); + +- manager_free_unit_name_maps(m); +- r = unit_file_build_name_map(&m->lookup_paths, &m->unit_id_map, &m->unit_name_map, &m->unit_path_cache); +- if (r < 0) +- return log_error_errno(r, "Failed to build name map: %m"); ++ manager_build_unit_path_cache(m); + + { + /* This block is (optionally) done with the reloading counter bumped */ +@@ -2862,9 +2903,8 @@ int manager_loop(Manager *m) { + assert(m); + assert(m->objective == MANAGER_OK); /* Ensure manager_startup() has been called */ + +- /* Release the path and unit name caches */ +- manager_free_unit_name_maps(m); +- // FIXME: once this happens, we cannot load any more units ++ /* Release the path cache */ ++ m->unit_path_cache = set_free_free(m->unit_path_cache); + + manager_check_finished(m); + +@@ -3539,10 +3579,7 @@ int manager_reload(Manager *m) { + + lookup_paths_log(&m->lookup_paths); + +- manager_free_unit_name_maps(m); +- r = unit_file_build_name_map(&m->lookup_paths, &m->unit_id_map, &m->unit_name_map, &m->unit_path_cache); +- if (r < 0) +- log_warning_errno(r, "Failed to build name map: %m"); ++ manager_build_unit_path_cache(m); + + /* First, enumerate what we can from kernel and suchlike */ + manager_enumerate_perpetual(m); +diff --git a/src/core/manager.h b/src/core/manager.h +index 9ca82ac..daeb454 100644 +--- a/src/core/manager.h ++++ b/src/core/manager.h +@@ -220,8 +220,6 @@ struct Manager { + + UnitFileScope unit_file_scope; + LookupPaths lookup_paths; +- Hashmap *unit_id_map; +- Hashmap *unit_name_map; + Set *unit_path_cache; + + char **transient_environment; /* The environment, as determined from config files, kernel cmdline and environment generators */ +diff --git a/src/core/unit.c b/src/core/unit.c +index f96e6e4..1b8d5d9 100644 +--- a/src/core/unit.c ++++ b/src/core/unit.c +@@ -959,9 +959,6 @@ int unit_merge_by_name(Unit *u, const char *name) { + Unit *other; + int r; + +- /* Either add name to u, or if a unit with name already exists, merge it with u. +- * If name is a template, do the same for name@instance, where instance is u's instance. */ +- + assert(u); + assert(name); + +diff --git a/src/shared/unit-file.c b/src/shared/unit-file.c +index bad92a3..cde38c4 100644 +--- a/src/shared/unit-file.c ++++ b/src/shared/unit-file.c +@@ -1,14 +1,7 @@ + /* SPDX-License-Identifier: LGPL-2.1+ */ + +-#include "dirent-util.h" +-#include "fd-util.h" +-#include "fs-util.h" + #include "macro.h" +-#include "path-lookup.h" +-#include "set.h" +-#include "stat-util.h" + #include "string-util.h" +-#include "strv.h" + #include "unit-file.h" + + bool unit_type_may_alias(UnitType type) { +@@ -101,358 +94,3 @@ int unit_validate_alias_symlink_and_warn(const char *filename, const char *targe + + return 0; + } +- +-#define FOLLOW_MAX 8 +- +-static int unit_ids_map_get( +- Hashmap *unit_ids_map, +- const char *unit_name, +- const char **ret_fragment_path) { +- +- /* Resolve recursively until we hit an absolute path, i.e. a non-aliased unit. +- * +- * We distinguish the case where unit_name was not found in the hashmap at all, and the case where +- * some symlink was broken. +- * +- * If a symlink target points to an instance name, then we also check for the template. */ +- +- const char *id = NULL; +- int r; +- +- for (unsigned n = 0; n < FOLLOW_MAX; n++) { +- const char *t = hashmap_get(unit_ids_map, id ?: unit_name); +- if (!t) { +- _cleanup_free_ char *template = NULL; +- +- if (!id) +- return -ENOENT; +- +- r = unit_name_template(id, &template); +- if (r == -EINVAL) +- return -ENXIO; /* we failed to find the symlink target */ +- if (r < 0) +- return log_error_errno(r, "Failed to determine template name for %s: %m", id); +- +- t = hashmap_get(unit_ids_map, template); +- if (!t) +- return -ENXIO; +- +- /* We successfully switched from instanced name to a template, let's continue */ +- } +- +- if (path_is_absolute(t)) { +- if (ret_fragment_path) +- *ret_fragment_path = t; +- return 0; +- } +- +- id = t; +- } +- +- return -ELOOP; +-} +- +-int unit_file_build_name_map( +- const LookupPaths *lp, +- Hashmap **ret_unit_ids_map, +- Hashmap **ret_unit_names_map, +- Set **ret_path_cache) { +- +- /* Build two mappings: any name → main unit (i.e. the end result of symlink resolution), unit name → +- * all aliases (i.e. the entry for a given key is a a list of all names which point to this key). The +- * key is included in the value iff we saw a file or symlink with that name. In other words, if we +- * have a key, but it is not present in the value for itself, there was an alias pointing to it, but +- * the unit itself is not loadable. +- * +- * At the same, build a cache of paths where to find units. +- */ +- +- _cleanup_hashmap_free_ Hashmap *ids = NULL, *names = NULL; +- _cleanup_set_free_free_ Set *paths = NULL; +- char **dir; +- int r; +- +- if (ret_path_cache) { +- paths = set_new(&path_hash_ops); +- if (!paths) +- return log_oom(); +- } +- +- STRV_FOREACH(dir, (char**) lp->search_path) { +- struct dirent *de; +- _cleanup_closedir_ DIR *d = NULL; +- +- d = opendir(*dir); +- if (!d) { +- if (errno != ENOENT) +- log_warning_errno(errno, "Failed to open \"%s\", ignoring: %m", *dir); +- continue; +- } +- +- FOREACH_DIRENT_ALL(de, d, log_warning_errno(errno, "Failed to read \"%s\", ignoring: %m", *dir)) { +- char *filename; +- _cleanup_free_ char *_filename_free = NULL, *simplified = NULL; +- const char *suffix, *dst = NULL; +- bool valid_unit_name; +- +- valid_unit_name = unit_name_is_valid(de->d_name, UNIT_NAME_ANY); +- +- /* We only care about valid units and dirs with certain suffixes, let's ignore the +- * rest. */ +- if (!valid_unit_name && +- !ENDSWITH_SET(de->d_name, ".wants", ".requires", ".d")) +- continue; +- +- filename = path_join(*dir, de->d_name); +- if (!filename) +- return log_oom(); +- +- if (ret_path_cache) { +- r = set_consume(paths, filename); +- if (r < 0) +- return log_oom(); +- /* We will still use filename below. This is safe because we know the set +- * holds a reference. */ +- } else +- _filename_free = filename; /* Make sure we free the filename. */ +- +- if (!valid_unit_name) +- continue; +- assert_se(suffix = strrchr(de->d_name, '.')); +- +- /* search_path is ordered by priority (highest first). If the name is already mapped +- * to something (incl. itself), it means that we have already seen it, and we should +- * ignore it here. */ +- if (hashmap_contains(ids, de->d_name)) +- continue; +- +- if (de->d_type == DT_LNK) { +- /* We don't explicitly check for alias loops here. unit_ids_map_get() which +- * limits the number of hops should be used to access the map. */ +- +- _cleanup_free_ char *target = NULL, *target_abs = NULL; +- +- r = readlinkat_malloc(dirfd(d), de->d_name, &target); +- if (r < 0) { +- log_warning_errno(r, "Failed to read symlink %s/%s, ignoring: %m", +- *dir, de->d_name); +- continue; +- } +- +- if (!path_is_absolute(target)) { +- target_abs = path_join(*dir, target); +- if (!target_abs) +- return log_oom(); +- +- free_and_replace(target, target_abs); +- } +- +- /* Get rid of "." and ".." components in target path */ +- r = chase_symlinks(target, lp->root_dir, CHASE_NOFOLLOW | CHASE_NONEXISTENT, &simplified); +- if (r < 0) { +- log_warning_errno(r, "Failed to resolve symlink %s pointing to %s, ignoring: %m", +- filename, target); +- continue; +- } +- +- /* Check if the symlink goes outside of our search path. +- * If yes, it's a linked unit file or mask, and we don't care about the target name. +- * Let's just store the link destination directly. +- * If not, let's verify that it's a good symlink. */ +- char *tail = path_startswith_strv(simplified, lp->search_path); +- if (tail) { +- bool self_alias; +- +- dst = basename(simplified); +- self_alias = streq(dst, de->d_name); +- +- if (is_path(tail)) +- log_full(self_alias ? LOG_DEBUG : LOG_WARNING, +- "Suspicious symlink %s→%s, treating as alias.", +- filename, simplified); +- +- r = unit_validate_alias_symlink_and_warn(filename, simplified); +- if (r < 0) +- continue; +- +- if (self_alias) { +- /* A self-alias that has no effect */ +- log_debug("%s: self-alias: %s/%s → %s, ignoring.", +- __func__, *dir, de->d_name, dst); +- continue; +- } +- +- log_debug("%s: alias: %s/%s → %s", __func__, *dir, de->d_name, dst); +- } else { +- dst = simplified; +- +- log_debug("%s: linked unit file: %s/%s → %s", __func__, *dir, de->d_name, dst); +- } +- +- } else { +- dst = filename; +- log_debug("%s: normal unit file: %s", __func__, dst); +- } +- +- r = hashmap_put_strdup(&ids, de->d_name, dst); +- if (r < 0) +- return log_warning_errno(r, "Failed to add entry to hashmap (%s→%s): %m", +- de->d_name, dst); +- } +- } +- +- /* Let's also put the names in the reverse db. */ +- Iterator it; +- const char *dummy, *src; +- HASHMAP_FOREACH_KEY(dummy, src, ids, it) { +- const char *dst; +- +- r = unit_ids_map_get(ids, src, &dst); +- if (r < 0) +- continue; +- +- if (null_or_empty_path(dst) != 0) +- continue; +- +- /* Do not treat instance symlinks that point to the template as aliases */ +- if (unit_name_is_valid(basename(dst), UNIT_NAME_TEMPLATE) && +- unit_name_is_valid(src, UNIT_NAME_INSTANCE)) +- continue; +- +- r = string_strv_hashmap_put(&names, basename(dst), src); +- if (r < 0) +- return log_warning_errno(r, "Failed to add entry to hashmap (%s→%s): %m", +- basename(dst), src); +- } +- +- *ret_unit_ids_map = TAKE_PTR(ids); +- *ret_unit_names_map = TAKE_PTR(names); +- if (ret_path_cache) +- *ret_path_cache = TAKE_PTR(paths); +- +- return 0; +-} +- +-int unit_file_find_fragment( +- Hashmap *unit_ids_map, +- Hashmap *unit_name_map, +- const char *unit_name, +- const char **ret_fragment_path, +- Set **ret_names) { +- +- const char *fragment = NULL; +- _cleanup_free_ char *template = NULL, *instance = NULL; +- _cleanup_set_free_free_ Set *names = NULL; +- char **t, **nnn; +- int r, name_type; +- +- /* Finds a fragment path, and returns the set of names: +- * if we have …/foo.service and …/foo-alias.service→foo.service, +- * and …/foo@.service and …/foo-alias@.service→foo@.service, +- * and …/foo@inst.service, +- * this should return: +- * foo.service → …/foo.service, {foo.service, foo-alias.service}, +- * foo-alias.service → …/foo.service, {foo.service, foo-alias.service}, +- * foo@.service → …/foo@.service, {foo@.service, foo-alias@.service}, +- * foo-alias@.service → …/foo@.service, {foo@.service, foo-alias@.service}, +- * foo@bar.service → …/foo@.service, {foo@bar.service, foo-alias@bar.service}, +- * foo-alias@bar.service → …/foo@.service, {foo@bar.service, foo-alias@bar.service}, +- * foo-alias@inst.service → …/foo@inst.service, {foo@inst.service, foo-alias@inst.service}. +- */ +- +- name_type = unit_name_to_instance(unit_name, &instance); +- if (name_type < 0) +- return name_type; +- +- names = set_new(&string_hash_ops); +- if (!names) +- return -ENOMEM; +- +- /* The unit always has its own name if it's not a template. */ +- if (IN_SET(name_type, UNIT_NAME_PLAIN, UNIT_NAME_INSTANCE)) { +- r = set_put_strdup(names, unit_name); +- if (r < 0) +- return r; +- } +- +- /* First try to load fragment under the original name */ +- r = unit_ids_map_get(unit_ids_map, unit_name, &fragment); +- if (r < 0 && !IN_SET(r, -ENOENT, -ENXIO)) +- return log_debug_errno(r, "Cannot load unit %s: %m", unit_name); +- +- if (fragment) { +- /* Add any aliases of the original name to the set of names */ +- nnn = hashmap_get(unit_name_map, basename(fragment)); +- STRV_FOREACH(t, nnn) { +- if (name_type == UNIT_NAME_INSTANCE && unit_name_is_valid(*t, UNIT_NAME_TEMPLATE)) { +- char *inst; +- +- r = unit_name_replace_instance(*t, instance, &inst); +- if (r < 0) +- return log_debug_errno(r, "Cannot build instance name %s+%s: %m", *t, instance); +- +- if (!streq(unit_name, inst)) +- log_debug("%s: %s has alias %s", __func__, unit_name, inst); +- +- log_info("%s: %s+%s → %s", __func__, *t, instance, inst); +- r = set_consume(names, inst); +- } else { +- if (!streq(unit_name, *t)) +- log_debug("%s: %s has alias %s", __func__, unit_name, *t); +- +- r = set_put_strdup(names, *t); +- } +- if (r < 0) +- return r; +- } +- } +- +- if (!fragment && name_type == UNIT_NAME_INSTANCE) { +- /* Look for a fragment under the template name */ +- +- r = unit_name_template(unit_name, &template); +- if (r < 0) +- return log_error_errno(r, "Failed to determine template name: %m"); +- +- r = unit_ids_map_get(unit_ids_map, template, &fragment); +- if (r < 0 && !IN_SET(r, -ENOENT, -ENXIO)) +- return log_debug_errno(r, "Cannot load template %s: %m", template); +- +- if (fragment) { +- /* Add any aliases of the original name to the set of names */ +- nnn = hashmap_get(unit_name_map, basename(fragment)); +- STRV_FOREACH(t, nnn) { +- _cleanup_free_ char *inst = NULL; +- const char *inst_fragment = NULL; +- +- r = unit_name_replace_instance(*t, instance, &inst); +- if (r < 0) +- return log_debug_errno(r, "Cannot build instance name %s+%s: %m", template, instance); +- +- /* Exclude any aliases that point in some other direction. */ +- r = unit_ids_map_get(unit_ids_map, inst, &inst_fragment); +- if (r < 0 && !IN_SET(r, -ENOENT, -ENXIO)) +- return log_debug_errno(r, "Cannot find instance fragment %s: %m", inst); +- +- if (inst_fragment && +- !streq(basename(inst_fragment), basename(fragment))) { +- log_debug("Instance %s has fragment %s and is not an alias of %s.", +- inst, inst_fragment, unit_name); +- continue; +- } +- +- if (!streq(unit_name, inst)) +- log_debug("%s: %s has alias %s", __func__, unit_name, inst); +- r = set_consume(names, TAKE_PTR(inst)); +- if (r < 0) +- return r; +- } +- } +- } +- +- *ret_fragment_path = fragment; +- *ret_names = TAKE_PTR(names); +- +- // FIXME: if instance, consider any unit names with different template name +- return 0; +-} +diff --git a/src/shared/unit-file.h b/src/shared/unit-file.h +index 52e17f7..e57f472 100644 +--- a/src/shared/unit-file.h ++++ b/src/shared/unit-file.h +@@ -3,12 +3,10 @@ + + #include + +-#include "hashmap.h" + #include "unit-name.h" + + typedef enum UnitFileState UnitFileState; + typedef enum UnitFileScope UnitFileScope; +-typedef struct LookupPaths LookupPaths; + + enum UnitFileState { + UNIT_FILE_ENABLED, +@@ -39,16 +37,3 @@ bool unit_type_may_alias(UnitType type) _const_; + bool unit_type_may_template(UnitType type) _const_; + + int unit_validate_alias_symlink_and_warn(const char *filename, const char *target); +- +-int unit_file_build_name_map( +- const LookupPaths *lp, +- Hashmap **ret_unit_ids_map, +- Hashmap **ret_unit_names_map, +- Set **ret_path_cache); +- +-int unit_file_find_fragment( +- Hashmap *unit_ids_map, +- Hashmap *unit_name_map, +- const char *unit_name, +- const char **ret_fragment_path, +- Set **names); +diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c +index 69063ee..48e0bad 100644 +--- a/src/systemctl/systemctl.c ++++ b/src/systemctl/systemctl.c +@@ -33,7 +33,6 @@ + #include "cgroup-util.h" + #include "copy.h" + #include "cpu-set-util.h" +-#include "dirent-util.h" + #include "dropin.h" + #include "efivars.h" + #include "env-util.h" +@@ -167,18 +166,12 @@ static bool arg_jobs_before = false; + static bool arg_jobs_after = false; + static char **arg_clean_what = NULL; + +-/* This is a global cache that will be constructed on first use. */ +-static Hashmap *cached_id_map = NULL; +-static Hashmap *cached_name_map = NULL; +- + STATIC_DESTRUCTOR_REGISTER(arg_wall, strv_freep); + STATIC_DESTRUCTOR_REGISTER(arg_root, freep); + STATIC_DESTRUCTOR_REGISTER(arg_types, strv_freep); + STATIC_DESTRUCTOR_REGISTER(arg_states, strv_freep); + STATIC_DESTRUCTOR_REGISTER(arg_properties, strv_freep); + STATIC_DESTRUCTOR_REGISTER(arg_clean_what, strv_freep); +-STATIC_DESTRUCTOR_REGISTER(cached_id_map, hashmap_freep); +-STATIC_DESTRUCTOR_REGISTER(cached_name_map, hashmap_freep); + + static int daemon_reload(int argc, char *argv[], void* userdata); + static int trivial_method(int argc, char *argv[], void *userdata); +@@ -2590,24 +2583,38 @@ static int unit_find_paths( + return log_error_errno(r, "Failed to get DropInPaths: %s", bus_error_message(&error, r)); + } + } else { +- const char *_path; +- _cleanup_set_free_free_ Set *names = NULL; ++ _cleanup_set_free_ Set *names = NULL; ++ _cleanup_free_ char *template = NULL; + +- if (!cached_name_map) { +- r = unit_file_build_name_map(lp, &cached_id_map, &cached_name_map, NULL); +- if (r < 0) +- return r; +- } ++ names = set_new(NULL); ++ if (!names) ++ return log_oom(); + +- r = unit_file_find_fragment(cached_id_map, cached_name_map, unit_name, &_path, &names); ++ r = unit_find_template_path(unit_name, lp, &path, &template); + if (r < 0) + return r; ++ if (r > 0) { ++ if (null_or_empty_path(path)) ++ /* The template is masked. Let's cut the process short. */ ++ return -ERFKILL; ++ ++ /* We found the unit file. If we followed symlinks, this name might be ++ * different then the unit_name with started with. Look for dropins matching ++ * that "final" name. */ ++ r = set_put(names, basename(path)); ++ } else if (!template) ++ /* No unit file, let's look for dropins matching the original name. ++ * systemd has fairly complicated rules (based on unit type and provenience), ++ * which units are allowed not to have the main unit file. We err on the ++ * side of including too many files, and always try to load dropins. */ ++ r = set_put(names, unit_name); ++ else ++ /* The cases where we allow a unit to exist without the main file are ++ * never valid for templates. Don't try to load dropins in this case. */ ++ goto not_found; + +- if (_path) { +- path = strdup(_path); +- if (!path) +- return log_oom(); +- } ++ if (r < 0) ++ return log_error_errno(r, "Failed to add unit name: %m"); + + if (ret_dropin_paths) { + r = unit_file_find_dropin_paths(arg_root, lp->search_path, NULL, +diff --git a/src/test/test-unit-file.c b/src/test/test-unit-file.c +index 988ac15..b626b5f 100644 +--- a/src/test/test-unit-file.c ++++ b/src/test/test-unit-file.c +@@ -25,50 +25,10 @@ static void test_unit_validate_alias_symlink_and_warn(void) { + assert_se(unit_validate_alias_symlink_and_warn("/path/a.slice", "/other/b.slice") == -EINVAL); + } + +-static void test_unit_file_build_name_map(char **ids) { +- _cleanup_(lookup_paths_free) LookupPaths lp = {}; +- _cleanup_hashmap_free_ Hashmap *unit_ids = NULL; +- _cleanup_hashmap_free_ Hashmap *unit_names = NULL; +- Iterator i; +- const char *k, *dst; +- char **v; +- +- assert_se(lookup_paths_init(&lp, UNIT_FILE_SYSTEM, 0, NULL) >= 0); +- +- assert_se(unit_file_build_name_map(&lp, &unit_ids, &unit_names, NULL) == 0); +- +- HASHMAP_FOREACH_KEY(dst, k, unit_ids, i) +- log_info("ids: %s → %s", k, dst); +- +- HASHMAP_FOREACH_KEY(v, k, unit_names, i) { +- _cleanup_free_ char *j = strv_join(v, ", "); +- log_info("aliases: %s ← %s", k, j); +- } +- +- char **id; +- STRV_FOREACH(id, ids) { +- const char *fragment, *name; +- Iterator it; +- _cleanup_set_free_free_ Set *names = NULL; +- log_info("*** %s ***", *id); +- r = unit_file_find_fragment(unit_ids, +- unit_names, +- *id, +- &fragment, +- &names); +- assert(r == 0); +- log_info("fragment: %s", fragment); +- log_info("names:"); +- SET_FOREACH(name, names, it) +- log_info(" %s", name); +- } +-} +- + int main(int argc, char **argv) { + test_setup_logging(LOG_DEBUG); + + test_unit_validate_alias_symlink_and_warn(); +- test_unit_file_build_name_map(strv_skip(argv, 1)); + + return 0; + } +diff --git a/test/TEST-15-DROPIN/test-dropin.sh b/test/TEST-15-DROPIN/test-dropin.sh +index 2cef5a3..f785680 100755 +--- a/test/TEST-15-DROPIN/test-dropin.sh ++++ b/test/TEST-15-DROPIN/test-dropin.sh +@@ -158,14 +158,14 @@ EOF + systemctl show -p Names,Requires bar@0 + systemctl show -p Names,Requires bar-alias@0 + check_ok bar@0 Names bar@0 +- check_ok bar@0 Names bar-alias@0 ++ check_ko bar@0 Names bar-alias@0 + + check_ok bar@0 After bar-template-after.device + + check_ok bar@0 Requires bar-0-requires.device +- check_ok bar@0 Requires bar-alias-0-requires.device ++ check_ko bar@0 Requires bar-alias-0-requires.device + check_ok bar@0 Requires bar-template-requires.device +- check_ok bar@0 Requires bar-alias-template-requires.device ++ check_ko bar@0 Requires bar-alias-template-requires.device + check_ko bar@0 Requires yup-template-requires.device + + check_ok bar-alias@0 After bar-template-after.device +@@ -181,15 +181,15 @@ EOF + systemctl show -p Names,Requires bar@1 + systemctl show -p Names,Requires bar-alias@1 + check_ok bar@1 Names bar@1 +- check_ok bar@1 Names bar-alias@1 ++ check_ko bar@1 Names bar-alias@1 + + check_ok bar@1 After bar-template-after.device + + check_ok bar@1 Requires bar-1-requires.device +- check_ok bar@1 Requires bar-alias-1-requires.device ++ check_ko bar@1 Requires bar-alias-1-requires.device + check_ok bar@1 Requires bar-template-requires.device + # See https://github.com/systemd/systemd/pull/13119#discussion_r308145418 +- check_ok bar@1 Requires bar-alias-template-requires.device ++ check_ko bar@1 Requires bar-alias-template-requires.device + check_ko bar@1 Requires yup-template-requires.device + check_ko bar@1 Requires yup-1-requires.device + +@@ -241,14 +241,14 @@ EOF + check_ko bar@3 Requires yup-template-requires.device + check_ko bar@3 Requires yup-3-requires.device + +- check_ko bar-alias@3 After bar-template-after.device ++ check_ok bar-alias@3 After bar-template-after.device + +- check_ko bar-alias@3 Requires bar-3-requires.device ++ check_ok bar-alias@3 Requires bar-3-requires.device + check_ok bar-alias@3 Requires bar-alias-3-requires.device +- check_ko bar-alias@3 Requires bar-template-requires.device ++ check_ok bar-alias@3 Requires bar-template-requires.device + check_ok bar-alias@3 Requires bar-alias-template-requires.device +- check_ok bar-alias@3 Requires yup-template-requires.device +- check_ok bar-alias@3 Requires yup-3-requires.device ++ check_ko bar-alias@3 Requires yup-template-requires.device ++ check_ko bar-alias@3 Requires yup-3-requires.device + + clear_services foo {bar,yup,bar-alias}@{,1,2,3} + } +@@ -267,7 +267,14 @@ test_alias_dropins () { + rm /etc/systemd/system/b1.service + clear_services a b + +- # Check that dependencies don't vary. ++ # A weird behavior: the dependencies for 'a' may vary. It can be ++ # changed by loading an alias... ++ # ++ # [1] 'a1' is loaded and then "renamed" into 'a'. 'a1' is therefore ++ # part of the names set so all its specific dropins are loaded. ++ # ++ # [2] 'a' is already loaded. 'a1' is simply only merged into 'a' so ++ # none of its dropins are loaded ('y' is missing from the deps). + echo "*** test 2" + create_services a x y + mkdir -p /etc/systemd/system/a1.service.wants/ +@@ -278,7 +285,7 @@ test_alias_dropins () { + check_ok a1 Wants y.service + systemctl start a + check_ok a1 Wants x.service # see [2] +- check_ok a1 Wants y.service ++ check_ko a1 Wants y.service + systemctl stop a x y + rm /etc/systemd/system/a1.service + +-- +1.8.3.1 + diff --git a/revert-shared-unit-file-add-a-function-to-validate-u.patch b/revert-shared-unit-file-add-a-function-to-validate-u.patch new file mode 100644 index 0000000000000000000000000000000000000000..89667563b160521dffa303b42674de1b8a3b53a9 --- /dev/null +++ b/revert-shared-unit-file-add-a-function-to-validate-u.patch @@ -0,0 +1,177 @@ +From 7d1e91d1a9504ab1bc03894038f90a8e87a4e982 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Tue, 2 Apr 2019 11:22:56 +0200 +Subject: [PATCH] shared/unit-file: add a function to validate unit alias + symlinks + +It turns out most possible symlinks are invalid, because the type has to match, +and template units can only be linked to template units. + +I'm not sure if the existing code made the same checks consistently. At least +I don't see the same rules expressed in a single place. + +revert shared unit file add a function to validate unit alias symlinks +--- + src/shared/unit-file.c | 73 ----------------------------------------------- + src/shared/unit-file.h | 2 -- + src/test/meson.build | 4 --- + src/test/test-unit-file.c | 34 ---------------------- + 4 files changed, 113 deletions(-) + delete mode 100644 src/test/test-unit-file.c + +diff --git a/src/shared/unit-file.c b/src/shared/unit-file.c +index cde38c4..deed7dc 100644 +--- a/src/shared/unit-file.c ++++ b/src/shared/unit-file.c +@@ -1,7 +1,6 @@ + /* SPDX-License-Identifier: LGPL-2.1+ */ + + #include "macro.h" +-#include "string-util.h" + #include "unit-file.h" + + bool unit_type_may_alias(UnitType type) { +@@ -22,75 +21,3 @@ bool unit_type_may_template(UnitType type) { + UNIT_TIMER, + UNIT_PATH); + } +- +-int unit_validate_alias_symlink_and_warn(const char *filename, const char *target) { +- const char *src, *dst; +- _cleanup_free_ char *src_instance = NULL, *dst_instance = NULL; +- UnitType src_unit_type, dst_unit_type; +- int src_name_type, dst_name_type; +- +- /* Check if the *alias* symlink is valid. This applies to symlinks like +- * /etc/systemd/system/dbus.service → dbus-broker.service, but not to .wants or .requires symlinks +- * and such. Neither does this apply to symlinks which *link* units, i.e. symlinks to outside of the +- * unit lookup path. +- * +- * -EINVAL is returned if the something is wrong with the source filename or the source unit type is +- * not allowed to symlink, +- * -EXDEV if the target filename is not a valid unit name or doesn't match the source. +- */ +- +- src = basename(filename); +- dst = basename(target); +- +- /* src checks */ +- +- src_name_type = unit_name_to_instance(src, &src_instance); +- if (src_name_type < 0) +- return log_notice_errno(src_name_type, +- "%s: not a valid unit name \"%s\": %m", filename, src); +- +- src_unit_type = unit_name_to_type(src); +- assert(src_unit_type >= 0); /* unit_name_to_instance() checked the suffix already */ +- +- if (!unit_type_may_alias(src_unit_type)) +- return log_notice_errno(SYNTHETIC_ERRNO(EINVAL), +- "%s: symlinks are not allowed for units of this type, rejecting.", +- filename); +- +- if (src_name_type != UNIT_NAME_PLAIN && +- !unit_type_may_template(src_unit_type)) +- return log_notice_errno(SYNTHETIC_ERRNO(EINVAL), +- "%s: templates not allowed for %s units, rejecting.", +- filename, unit_type_to_string(src_unit_type)); +- +- /* dst checks */ +- +- dst_name_type = unit_name_to_instance(dst, &dst_instance); +- if (dst_name_type < 0) +- return log_notice_errno(dst_name_type == -EINVAL ? SYNTHETIC_ERRNO(EXDEV) : dst_name_type, +- "%s points to \"%s\" which is not a valid unit name: %m", +- filename, dst); +- +- if (!(dst_name_type == src_name_type || +- (src_name_type == UNIT_NAME_INSTANCE && dst_name_type == UNIT_NAME_TEMPLATE))) +- return log_notice_errno(SYNTHETIC_ERRNO(EXDEV), +- "%s: symlink target name type \"%s\" does not match source, rejecting.", +- filename, dst); +- +- if (dst_name_type == UNIT_NAME_INSTANCE) { +- assert(src_instance); +- assert(dst_instance); +- if (!streq(src_instance, dst_instance)) +- return log_notice_errno(SYNTHETIC_ERRNO(EXDEV), +- "%s: unit symlink target \"%s\" instance name doesn't match, rejecting.", +- filename, dst); +- } +- +- dst_unit_type = unit_name_to_type(dst); +- if (dst_unit_type != src_unit_type) +- return log_notice_errno(SYNTHETIC_ERRNO(EXDEV), +- "%s: symlink target \"%s\" has incompatible suffix, rejecting.", +- filename, dst); +- +- return 0; +-} +diff --git a/src/shared/unit-file.h b/src/shared/unit-file.h +index e57f472..2b9df65 100644 +--- a/src/shared/unit-file.h ++++ b/src/shared/unit-file.h +@@ -35,5 +35,3 @@ enum UnitFileScope { + + bool unit_type_may_alias(UnitType type) _const_; + bool unit_type_may_template(UnitType type) _const_; +- +-int unit_validate_alias_symlink_and_warn(const char *filename, const char *target); +diff --git a/src/test/meson.build b/src/test/meson.build +index de31e97..5625e68 100644 +--- a/src/test/meson.build ++++ b/src/test/meson.build +@@ -137,10 +137,6 @@ tests += [ + [], + 'ENABLE_EFI'], + +- [['src/test/test-unit-file.c'], +- [], +- []], +- + [['src/test/test-unit-name.c', + 'src/test/test-helper.c'], + [libcore, +diff --git a/src/test/test-unit-file.c b/src/test/test-unit-file.c +deleted file mode 100644 +index b626b5f..0000000 +--- a/src/test/test-unit-file.c ++++ /dev/null +@@ -1,34 +0,0 @@ +-/* SPDX-License-Identifier: LGPL-2.1+ */ +- +-#include "path-lookup.h" +-#include "set.h" +-#include "strv.h" +-#include "tests.h" +-#include "unit-file.h" +- +-static void test_unit_validate_alias_symlink_and_warn(void) { +- log_info("/* %s */", __func__); +- +- assert_se(unit_validate_alias_symlink_and_warn("/path/a.service", "/other/b.service") == 0); +- assert_se(unit_validate_alias_symlink_and_warn("/path/a.service", "/other/b.socket") == -EXDEV); +- assert_se(unit_validate_alias_symlink_and_warn("/path/a.service", "/other/b.foobar") == -EXDEV); +- assert_se(unit_validate_alias_symlink_and_warn("/path/a@.service", "/other/b@.service") == 0); +- assert_se(unit_validate_alias_symlink_and_warn("/path/a@.service", "/other/b@.socket") == -EXDEV); +- assert_se(unit_validate_alias_symlink_and_warn("/path/a@XXX.service", "/other/b@YYY.service") == -EXDEV); +- assert_se(unit_validate_alias_symlink_and_warn("/path/a@XXX.service", "/other/b@YYY.socket") == -EXDEV); +- assert_se(unit_validate_alias_symlink_and_warn("/path/a@.service", "/other/b@YYY.service") == -EXDEV); +- assert_se(unit_validate_alias_symlink_and_warn("/path/a@XXX.service", "/other/b@XXX.service") == 0); +- assert_se(unit_validate_alias_symlink_and_warn("/path/a@XXX.service", "/other/b@.service") == 0); +- assert_se(unit_validate_alias_symlink_and_warn("/path/a@.service", "/other/b.service") == -EXDEV); +- assert_se(unit_validate_alias_symlink_and_warn("/path/a.service", "/other/b@.service") == -EXDEV); +- assert_se(unit_validate_alias_symlink_and_warn("/path/a@.slice", "/other/b.slice") == -EINVAL); +- assert_se(unit_validate_alias_symlink_and_warn("/path/a.slice", "/other/b.slice") == -EINVAL); +-} +- +-int main(int argc, char **argv) { +- test_setup_logging(LOG_DEBUG); +- +- test_unit_validate_alias_symlink_and_warn(); +- +- return 0; +-} +-- +1.8.3.1 + diff --git a/rules-add-elevator-kernel-command-line-parameter.patch b/rules-add-elevator-kernel-command-line-parameter.patch new file mode 100644 index 0000000000000000000000000000000000000000..9b2c69ef346250de1962790f7183a32d10e55785 --- /dev/null +++ b/rules-add-elevator-kernel-command-line-parameter.patch @@ -0,0 +1,43 @@ +From 1255584bb0a595fb555af7e14230ab1b7aa6adcd Mon Sep 17 00:00:00 2001 +From: Lukas Nykryn +Date: Tue, 12 Feb 2019 16:58:16 +0100 +Subject: [PATCH] rules: add elevator= kernel command line parameter + +Kernel removed the elevator= option + +Resolves: #1670126 + +--- + rules/40-elevator.rules | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + create mode 100644 rules/40-elevator.rules + +diff --git a/rules/40-elevator.rules b/rules/40-elevator.rules +new file mode 100644 +index 0000000..dbe8fc8 +--- /dev/null ++++ b/rules/40-elevator.rules +@@ -0,0 +1,20 @@ ++# We aren't adding devices skip the elevator check ++ACTION!="add", GOTO="sched_out" ++ ++SUBSYSTEM!="block", GOTO="sched_out" ++ENV{DEVTYPE}!="disk", GOTO="sched_out" ++ ++# Technically, dm-multipath can be configured to use an I/O scheduler. ++# However, there are races between the 'add' uevent and the linking in ++# of the queue/scheduler sysfs file. For now, just skip dm- devices. ++KERNEL=="dm-*|md*", GOTO="sched_out" ++ ++# Skip bio-based devices, which don't support an I/O scheduler. ++ATTR{queue/scheduler}=="none", GOTO="sched_out" ++ ++# If elevator= is specified on the kernel command line, change the ++# scheduler to the one specified. ++IMPORT{cmdline}="elevator" ++ENV{elevator}!="", ATTR{queue/scheduler}="$env{elevator}" ++ ++LABEL="sched_out" +-- +1.8.3.1 + diff --git a/rules-add-rule-for-naming-Dell-iDRAC-USB-Virtual-NIC.patch b/rules-add-rule-for-naming-Dell-iDRAC-USB-Virtual-NIC.patch new file mode 100644 index 0000000000000000000000000000000000000000..a9a20f1462bd6603e2687c0277cedddc7ac4b019 --- /dev/null +++ b/rules-add-rule-for-naming-Dell-iDRAC-USB-Virtual-NIC.patch @@ -0,0 +1,40 @@ +From 2991b22f5f40a66ad1cc088e502e7f40ae1806c2 Mon Sep 17 00:00:00 2001 +From: Michal Sekletar +Date: Mon, 22 Sep 2014 07:53:52 +0200 +Subject: rules: add rule for naming Dell iDRAC USB Virtual NIC + as 'idrac' + +Related: #1523227 +--- + rules/73-idrac.rules | 6 ++++++ + rules/meson.build | 1 + + 2 files changed, 7 insertions(+) + create mode 100644 rules/73-idrac.rules + +diff --git a/rules/73-idrac.rules b/rules/73-idrac.rules +new file mode 100644 +index 0000000..d67fc42 +--- /dev/null ++++ b/rules/73-idrac.rules +@@ -0,0 +1,6 @@ ++# do not edit this file, it will be overwritten on update ++ ++# On Dell PowerEdge systems, the iDRAC7 and later support a USB Virtual NIC ++# with terminates in the iDRAC. Help identify this with 'idrac' ++ ++ACTION=="add", SUBSYSTEM=="net", SUBSYSTEMS=="usb", ATTRS{idVendor}=="413c", ATTRS{idProduct}=="a102", NAME="idrac" +diff --git a/rules/meson.build b/rules/meson.build +index e7e4362..e04a18a 100644 +--- a/rules/meson.build ++++ b/rules/meson.build +@@ -17,6 +17,7 @@ rules = files(''' + 70-joystick.rules + 70-mouse.rules + 70-touchpad.rules ++ 73-idrac.rules + 75-net-description.rules + 75-probe_mtd.rules + 78-sound-card.rules +-- +1.8.3.1 + diff --git a/rules-add-the-rule-that-adds-elevator-kernel-command.patch b/rules-add-the-rule-that-adds-elevator-kernel-command.patch new file mode 100644 index 0000000000000000000000000000000000000000..dd20b73f0b16b12f0cafbbdaa7aca5f06c369cb4 --- /dev/null +++ b/rules-add-the-rule-that-adds-elevator-kernel-command.patch @@ -0,0 +1,27 @@ +From 16d1f6e5122038fa24392e166a0a88c6cab41dd0 Mon Sep 17 00:00:00 2001 +From: Lukas Nykryn +Date: Tue, 26 Feb 2019 15:22:38 +0100 +Subject: [PATCH] rules: add the rule that adds elevator= kernel + command line parameter + +Resolves: #1670126 + +--- + rules/meson.build | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/rules/meson.build b/rules/meson.build +index 1da958b..043313a 100644 +--- a/rules/meson.build ++++ b/rules/meson.build +@@ -1,6 +1,7 @@ + # SPDX-License-Identifier: LGPL-2.1+ + + rules = files(''' ++ 40-elevator.rules + 60-block.rules + 60-block-scheduler.rules + 60-cdrom_id.rules +-- +2.19.1 + diff --git a/sd-bus-properly-initialize-containers.patch b/sd-bus-properly-initialize-containers.patch new file mode 100644 index 0000000000000000000000000000000000000000..a6583b82977dfeb64437b1849de90e7f0724c834 --- /dev/null +++ b/sd-bus-properly-initialize-containers.patch @@ -0,0 +1,31 @@ +From 220a60a61a91153fd8e49e58884b9b0b904888f6 Mon Sep 17 00:00:00 2001 +From: Jan Synacek +Date: Wed, 31 Oct 2018 12:50:19 +0100 +Subject: [PATCH] sd-bus: properly initialize containers + +Fixes a SIGSEGV introduced by commit 38a5315a3a6fab745d8c86ff9e486faaf50b28d1. +The same problem doesn't exist upstream, as the container structure +there is initialized using a compound literal, which is zeroed out by +default. + +Related: #1635435 + +--- + src/libsystemd/sd-bus/bus-message.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/libsystemd/sd-bus/bus-message.c b/src/libsystemd/sd-bus/bus-message.c +index eb029e4..e0c8338 100644 +--- a/src/libsystemd/sd-bus/bus-message.c ++++ b/src/libsystemd/sd-bus/bus-message.c +@@ -2051,6 +2051,7 @@ _public_ int sd_bus_message_open_container( + .enclosing = type, + .signature = TAKE_PTR(signature), + .array_size = array_size, ++ .peeked_signature = NULL, + .before = before, + .begin = begin, + .need_offsets = need_offsets, +-- +2.19.1 + diff --git a/systemd-Fix-busctl-crash-on-aarch64-when-setting-out.patch b/systemd-Fix-busctl-crash-on-aarch64-when-setting-out.patch new file mode 100644 index 0000000000000000000000000000000000000000..62ec61d75cb3f16dc4f76e3f7aa34e7e4c468241 --- /dev/null +++ b/systemd-Fix-busctl-crash-on-aarch64-when-setting-out.patch @@ -0,0 +1,52 @@ +From bec31cf5f0037dd049299e8665e03fc74024e357 Mon Sep 17 00:00:00 2001 +From: Alin Popa +Date: Fri, 14 Feb 2020 09:33:43 +0100 +Subject: [PATCH] systemd: Fix busctl crash on aarch64 when setting output + table format + +The enum used for column names is integer type while table_set_display() is parsing +arguments on size_t alignment which may result in assert in table_set_display() if +the size between types missmatch. This patch cast the enums to size_t. +An alternative solution would be to change the table_set_display() function +arguments to unsigned type. +--- + src/busctl/busctl.c | 22 ++++++++++++++++++++-- + 1 file changed, 20 insertions(+), 2 deletions(-) + +diff --git a/src/busctl/busctl.c b/src/busctl/busctl.c +index 5f3d5dd..b4e133f 100644 +--- a/src/busctl/busctl.c ++++ b/src/busctl/busctl.c +@@ -212,9 +212,27 @@ static int list_bus_names(int argc, char **argv, void *userdata) { + return log_error_errno(r, "Failed to set sort column: %m"); + + if (arg_show_machine) +- r = table_set_display(table, COLUMN_NAME, COLUMN_PID, COLUMN_PROCESS, COLUMN_USER, COLUMN_CONNECTION, COLUMN_UNIT, COLUMN_SESSION, COLUMN_DESCRIPTION, COLUMN_MACHINE, (size_t) -1); ++ r = table_set_display(table, (size_t) COLUMN_NAME, ++ (size_t) COLUMN_PID, ++ (size_t) COLUMN_PROCESS, ++ (size_t) COLUMN_USER, ++ (size_t) COLUMN_CONNECTION, ++ (size_t) COLUMN_UNIT, ++ (size_t) COLUMN_SESSION, ++ (size_t) COLUMN_DESCRIPTION, ++ (size_t) COLUMN_MACHINE, ++ (size_t) -1); + else +- r = table_set_display(table, COLUMN_NAME, COLUMN_PID, COLUMN_PROCESS, COLUMN_USER, COLUMN_CONNECTION, COLUMN_UNIT, COLUMN_SESSION, COLUMN_DESCRIPTION, (size_t) -1); ++ r = table_set_display(table, (size_t) COLUMN_NAME, ++ (size_t) COLUMN_PID, ++ (size_t) COLUMN_PROCESS, ++ (size_t) COLUMN_USER, ++ (size_t) COLUMN_CONNECTION, ++ (size_t) COLUMN_UNIT, ++ (size_t) COLUMN_SESSION, ++ (size_t) COLUMN_DESCRIPTION, ++ (size_t) -1); ++ + if (r < 0) + return log_error_errno(r, "Failed to set columns to display: %m"); + +-- +1.8.3.1 + diff --git a/systemd.spec b/systemd.spec index 86c75ed0bb56bd9a3568d4c675d2f0072446a8f2..931a9444fda7e6309ae8853607a8d7be38e4043b 100644 --- a/systemd.spec +++ b/systemd.spec @@ -16,7 +16,7 @@ Name: systemd Url: https://www.freedesktop.org/wiki/Software/systemd Version: 243 -Release: 19 +Release: 21 License: MIT and LGPLv2+ and GPLv2+ Summary: System and Service Manager @@ -62,6 +62,29 @@ Patch0015: CVE-2020-1712-5.patch Patch0016: sd-journal-close-journal-files-that-were-deleted-by-.patch Patch0017: pid1-bump-DefaultTasksMax-to-80-of-the-kernel-pid.ma.patch Patch0018: fix-two-VF-virtual-machines-have-same-mac-address.patch +Patch0019: logind-set-RemoveIPC-to-false-by-default.patch +Patch0020: rules-add-rule-for-naming-Dell-iDRAC-USB-Virtual-NIC.patch +Patch0021: unit-don-t-add-Requires-for-tmp.mount.patch +Patch0022: Revert-sysctl.d-switch-net.ipv4.conf.all.rp_filter-f.patch +Patch2023: rules-add-elevator-kernel-command-line-parameter.patch +Patch2024: rules-add-the-rule-that-adds-elevator-kernel-command.patch +Patch2025: units-add-Install-section-to-tmp.mount.patch +Patch0026: Make-systemd-udevd.service-start-after-systemd-remou.patch +Patch0027: udev-virsh-shutdown-vm.patch +Patch0028: fix-fd-leak-in-no-memory-condition.patch +Patch0029: dbus-execute-avoid-extra-strdup.patch +Patch0030: Avoid-tmp-being-mounted-as-tmpfs-without-the-user-s-.patch +Patch0031: sd-bus-properly-initialize-containers.patch +Patch0032: Revert-core-one-step-back-again-for-nspawn-we-actual.patch +Patch0033: journal-don-t-enable-systemd-journald-audit.socket-b.patch + +# The patch of 0026~0029 resolve the pid1 memory leaks +Patch0034: revert-pid1-drop-unit-caches-only-based-on-mtime.patch +Patch0035: revert-analyze-add-unit-files-to-dump-the-unit-fragm.patch +Patch0036: revert-pid1-use-a-cache-for-all-unit-aliases.patch +Patch0037: revert-shared-unit-file-add-a-function-to-validate-u.patch + +Patch0038: systemd-Fix-busctl-crash-on-aarch64-when-setting-out.patch #openEuler Patch9002: 1509-fix-journal-file-descriptors-leak-problems.patch @@ -1353,6 +1376,8 @@ fi %{_udevhwdbdir}/60-sensor.hwdb %{_udevhwdbdir}/70-mouse.hwdb %{_udevrulesdir}/40-openEuler.rules +%{_udevrulesdir}/40-elevator.rules +%{_udevrulesdir}/73-idrac.rules %{_udevrulesdir}/60-block.rules %{_udevrulesdir}/60-input-id.rules %{_udevrulesdir}/71-seat.rules @@ -1465,6 +1490,18 @@ fi %exclude /usr/share/man/man3/* %changelog +* Mon Apr 27 2020 openEuler Buildteam - 243-21 +- Type:enhancement +- ID:NA +- SUG:NA +- DESC:resolve memleak of pid1 and add some patches + +* Thu Apr 9 2020 openEuler Buildteam - 243-20 +- Type:enhancement +- ID:NA +- SUG:NA +- DESC:delete redundant info in spec + * Wed Mar 25 2020 openEuler Buildteam - 243-19 - Type:enhancement - ID:NA diff --git a/udev-virsh-shutdown-vm.patch b/udev-virsh-shutdown-vm.patch new file mode 100644 index 0000000000000000000000000000000000000000..194093109b6bf6e35be30c0bba885996e69f2566 --- /dev/null +++ b/udev-virsh-shutdown-vm.patch @@ -0,0 +1,23 @@ +From 3d5e0620b4a3298620c8d985cec42772c7f77c6d Mon Sep 17 00:00:00 2001 +From: openEuler Buildteam +Date: Thu, 31 Jan 2019 02:24:16 -0500 +Subject: [PATCH] systemd:virsh shutdown vm + +--- + src/login/70-power-switch.rules | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/login/70-power-switch.rules b/src/login/70-power-switch.rules +index d69e65b..cb77f7a 100644 +--- a/src/login/70-power-switch.rules ++++ b/src/login/70-power-switch.rules +@@ -11,5 +11,6 @@ ACTION=="remove", GOTO="power_switch_end" + + SUBSYSTEM=="input", KERNEL=="event*", ENV{ID_INPUT_SWITCH}=="1", TAG+="power-switch" + SUBSYSTEM=="input", KERNEL=="event*", ENV{ID_INPUT_KEY}=="1", TAG+="power-switch" ++SUBSYSTEM=="input", KERNEL=="event*", SUBSYSTEMS=="platform", ATTRS{keys}=="116", TAG+="power-switch" + + LABEL="power_switch_end" +-- +1.8.3.1 + diff --git a/unit-don-t-add-Requires-for-tmp.mount.patch b/unit-don-t-add-Requires-for-tmp.mount.patch new file mode 100644 index 0000000000000000000000000000000000000000..99d5db276304c942b71c5b206f5be9be567b5c61 --- /dev/null +++ b/unit-don-t-add-Requires-for-tmp.mount.patch @@ -0,0 +1,27 @@ +From 03e52d33bbdea731eaa79545bb1d30c5b21abe3d Mon Sep 17 00:00:00 2001 +From: Lukas Nykryn +Date: Mon, 5 Sep 2016 12:47:09 +0200 +Subject: [PATCH] unit: don't add Requires for tmp.mount + +Resolves: #1619292 + +--- + src/core/unit.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/core/unit.c b/src/core/unit.c +index c9f756c..721d8d6 100644 +--- a/src/core/unit.c ++++ b/src/core/unit.c +@@ -1421,7 +1421,7 @@ static int unit_add_mount_dependencies(Unit *u) { + if (r < 0) + return r; + +- if (m->fragment_path) { ++ if (m->fragment_path && !streq(m->id, "tmp.mount")) { + r = unit_add_dependency(u, UNIT_REQUIRES, m, true, di.origin_mask); + if (r < 0) + return r; +-- +1.8.3.1 + diff --git a/units-add-Install-section-to-tmp.mount.patch b/units-add-Install-section-to-tmp.mount.patch new file mode 100644 index 0000000000000000000000000000000000000000..b1a615a0decf92a4dafbb8f7f3a2f36eef6b8f06 --- /dev/null +++ b/units-add-Install-section-to-tmp.mount.patch @@ -0,0 +1,25 @@ +From bb3d205bea1c83cbd0e27b504f5f1faa884fb602 Mon Sep 17 00:00:00 2001 +From: Jan Synacek +Date: Tue, 22 Jan 2019 10:28:42 +0100 +Subject: [PATCH] units: add [Install] section to tmp.mount + +Resolves: #1667065 +--- + units/tmp.mount | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/units/tmp.mount b/units/tmp.mount +index 742d863..b558047 100644 +--- a/units/tmp.mount ++++ b/units/tmp.mount +@@ -22,3 +22,7 @@ What=tmpfs + Where=/tmp + Type=tmpfs + Options=mode=1777,strictatime,nosuid,nodev ++ ++# Make 'systemctl enable tmp.mount' work: ++[Install] ++WantedBy=local-fs.target +-- +1.8.3.1 +