From 934e749e18bc0641a3dc8d83c4f16a2ba4c8d966 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 29 Apr 2016 17:31:02 +0200 Subject: core: refuse merging on units when the unit type does not support alias The concept of merging units exists so that we can create Unit objects for a number of names early, and then load them only later, possibly merging units which then turn out to be symlinked to other names. This of course only makes sense for unit types where multiple names per unit are supported. For all others, let's refuse the merge operation early. --- src/core/unit.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/core/unit.c b/src/core/unit.c index cb79c7c6b1..4a129ffd5e 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -720,6 +720,9 @@ int unit_merge(Unit *u, Unit *other) { if (!u->instance != !other->instance) return -EINVAL; + if (UNIT_VTABLE(u)->no_alias) /* Merging only applies to unit names that support aliases */ + return -EEXIST; + if (other->load_state != UNIT_STUB && other->load_state != UNIT_NOT_FOUND) return -EEXIST; @@ -776,9 +779,9 @@ int unit_merge(Unit *u, Unit *other) { } int unit_merge_by_name(Unit *u, const char *name) { + _cleanup_free_ char *s = NULL; Unit *other; int r; - _cleanup_free_ char *s = NULL; assert(u); assert(name); -- cgit v1.2.3-54-g00ecf From 454f0f8680ebbded135e8575b4d9615b427fdf76 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 29 Apr 2016 17:33:29 +0200 Subject: hashmap: optimize set_put_strdup() a bit Hashing should be quicker than allocating, hence let's first check if the string already exists and only then allocate a new copy for it. --- src/basic/hashmap.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/basic/hashmap.c b/src/basic/hashmap.c index 85b8d812b3..49a0479592 100644 --- a/src/basic/hashmap.c +++ b/src/basic/hashmap.c @@ -1773,20 +1773,18 @@ int set_consume(Set *s, void *value) { int set_put_strdup(Set *s, const char *p) { char *c; - int r; assert(s); assert(p); + if (set_contains(s, (char*) p)) + return 0; + c = strdup(p); if (!c) return -ENOMEM; - r = set_consume(s, c); - if (r == -EEXIST) - return 0; - - return r; + return set_consume(s, c); } int set_put_strdupv(Set *s, char **l) { -- cgit v1.2.3-54-g00ecf From a837f0880362c190254619ebbb8bad20603211f4 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 29 Apr 2016 17:37:33 +0200 Subject: core: when encountering a symlink alias for non-aliasable units warn nicely If the user defines a symlink alias for a unit whose type does not support aliasing, detect this early and print a nice warning. Fixe: #2730 --- src/core/load-fragment.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c index c4566f7709..31b995aa6a 100644 --- a/src/core/load-fragment.c +++ b/src/core/load-fragment.c @@ -3427,10 +3427,10 @@ int config_parse_protect_system( #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; - char *id = NULL; assert(filename); assert(*filename); @@ -3452,7 +3452,6 @@ static int open_follow(char **filename, FILE **_f, Set *names, char **_final) { * 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); @@ -3492,6 +3491,7 @@ static int open_follow(char **filename, FILE **_f, Set *names, char **_final) { *_f = f; *_final = id; + return 0; } @@ -3552,13 +3552,13 @@ static int merge_by_names(Unit **u, Set *names, const char *id) { } static int load_from_path(Unit *u, const char *path) { - int r; _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); @@ -3597,18 +3597,14 @@ static int load_from_path(Unit *u, const char *path) { r = -ENOENT; else r = open_follow(&filename, &f, symlink_names, &id); + if (r >= 0) + break; + filename = mfree(filename); + if (r != -ENOENT) + return r; - if (r < 0) { - filename = mfree(filename); - if (r != -ENOENT) - return r; - - /* Empty the symlink names for the next run */ - set_clear_free(symlink_names); - continue; - } - - break; + /* Empty the symlink names for the next run */ + set_clear_free(symlink_names); } } @@ -3616,6 +3612,11 @@ static int load_from_path(Unit *u, const char *path) { /* Hmm, no suitable file found? */ return 0; + if (UNIT_VTABLE(u)->no_alias && 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) -- cgit v1.2.3-54-g00ecf From f4bf8d2f45b02c26234219d07bfd3a41290cc84e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 29 Apr 2016 17:48:07 +0200 Subject: man: document that some unit types do not support unit aliases via symlinks --- man/systemd.automount.xml | 15 +++++++-------- man/systemd.mount.xml | 14 ++++++-------- man/systemd.slice.xml | 3 +++ man/systemd.swap.xml | 13 ++++++------- man/systemd.unit.xml | 13 ++++++------- 5 files changed, 28 insertions(+), 30 deletions(-) diff --git a/man/systemd.automount.xml b/man/systemd.automount.xml index 93bae2a6dc..a43dc981bd 100644 --- a/man/systemd.automount.xml +++ b/man/systemd.automount.xml @@ -66,14 +66,13 @@ [Install] sections. The automount specific configuration options are configured in the [Automount] section. - Automount units must be named after the automount - directories they control. Example: the automount point - /home/lennart must be - configured in a unit file - home-lennart.automount. For details about the - escaping logic used to convert a file system path to a unit name - see - systemd.unit5. + Automount units must be named after the automount directories they control. Example: the automount point + /home/lennart must be configured in a unit file + home-lennart.automount. For details about the escaping logic used to convert a file system + path to a unit name see + systemd.unit5. Note that + automount units cannot be templated, nor is it possible to add multiple names to an automount unit by creating + additional symlinks to its unit file. For each automount unit file a matching mount unit file (see systemd.mount5 diff --git a/man/systemd.mount.xml b/man/systemd.mount.xml index f116782b40..bf56a49e58 100644 --- a/man/systemd.mount.xml +++ b/man/systemd.mount.xml @@ -82,14 +82,12 @@ will refuse options that are not listed in /etc/fstab if it is not run as UID 0. - Mount units must be named after the mount point directories - they control. Example: the mount point - /home/lennart must be - configured in a unit file home-lennart.mount. - For details about the escaping logic used to convert a file system - path to a unit name, see - systemd.unit5. - Note that mount units cannot be templated. + Mount units must be named after the mount point directories they control. Example: the mount point /home/lennart must be configured in a unit file home-lennart.mount. + For details about the escaping logic used to convert a file system path to a unit name, see + systemd.unit5. Note that mount + units cannot be templated, nor is possible to add multiple names to a mount unit by creating additional symlinks to + it. Optionally, a mount unit may be accompanied by an automount unit, to allow on-demand or parallelized mounting. See diff --git a/man/systemd.slice.xml b/man/systemd.slice.xml index 16247628af..eee98d99ee 100644 --- a/man/systemd.slice.xml +++ b/man/systemd.slice.xml @@ -71,6 +71,9 @@ the root slice -.slice. + Note that slice units cannot be templated, nor is possible to add multiple names to a slice unit by creating + additional symlinks to it. + By default, service and scope units are placed in system.slice, virtual machines and containers registered with diff --git a/man/systemd.swap.xml b/man/systemd.swap.xml index 6fc4c7bf13..cf4e1ba839 100644 --- a/man/systemd.swap.xml +++ b/man/systemd.swap.xml @@ -78,13 +78,12 @@ which configure resource control settings for these processes of the unit. - Swap units must be named after the devices - or files they control. Example: the swap device - /dev/sda5 must be configured in a - unit file dev-sda5.swap. For details about - the escaping logic used to convert a file system path to a unit - name, see - systemd.unit5. + Swap units must be named after the devices or files they control. Example: the swap device /dev/sda5 must be configured in a unit file dev-sda5.swap. For + details about the escaping logic used to convert a file system path to a unit name, see + systemd.unit5. Note that swap + units cannot be templated, nor is possible to add multiple names to a swap unit by creating additional symlinks to + it. diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml index 7993301167..69f56e3f0a 100644 --- a/man/systemd.unit.xml +++ b/man/systemd.unit.xml @@ -1102,13 +1102,12 @@ Alias= - A space-separated list of additional names - this unit shall be installed under. The names listed here must - have the same suffix (i.e. type) as the unit file name. This - option may be specified more than once, in which case all - listed names are used. At installation time, - systemctl enable will create symlinks from - these names to the unit filename. + A space-separated list of additional names this unit shall be installed under. The names listed + here must have the same suffix (i.e. type) as the unit file name. This option may be specified more than once, + in which case all listed names are used. At installation time, systemctl enable will create + symlinks from these names to the unit filename. Note that not all unit types support such alias names, and this + setting is not supported for them. Specifically, mount, slice, swap, and automount units do not support + aliasing. -- cgit v1.2.3-54-g00ecf