From: Zbigniew Jędrzejewski-Szmek Date: Fri, 27 Jun 2014 16:12:07 +0000 (-0400) Subject: Move x-systemd-device.timeout handling from core to fstab-generator X-Git-Tag: v215~89 X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=commitdiff_plain;h=2968644080fd103062f070e83edd620e0a58c44d Move x-systemd-device.timeout handling from core to fstab-generator Instead of adjusting job timeouts in the core, let fstab-generator write out a dropin snippet with the appropriate JobTimeout. x-systemd-device.timeout option is removed from Options= line in the generated unit. The functions to write dropins are moved from core/unit.c to shared/dropin.c, to make them available outside of core. generator.c is moved to libsystemd-label, because it now uses functions defined in dropin.c, which are in libsystemd-label. --- diff --git a/Makefile.am b/Makefile.am index 60f69fe32..783f5fe18 100644 --- a/Makefile.am +++ b/Makefile.am @@ -816,8 +816,6 @@ libsystemd_shared_la_SOURCES = \ src/shared/bus-label.c \ src/shared/bus-label.h \ src/shared/gpt.h \ - src/shared/generator.h \ - src/shared/generator.c \ src/shared/clean-ipc.h \ src/shared/clean-ipc.c \ src/shared/login-shared.c \ @@ -874,7 +872,11 @@ libsystemd_label_la_SOURCES = \ src/shared/fileio-label.c \ src/shared/fileio-label.h \ src/shared/dev-setup.c \ - src/shared/dev-setup.h + src/shared/dev-setup.h \ + src/shared/dropin.c \ + src/shared/dropin.h \ + src/shared/generator.h \ + src/shared/generator.c libsystemd_label_la_CFLAGS = \ $(AM_CFLAGS) \ diff --git a/src/core/mount.c b/src/core/mount.c index aea2ab17c..102bbef91 100644 --- a/src/core/mount.c +++ b/src/core/mount.c @@ -418,57 +418,6 @@ static int mount_add_default_dependencies(Mount *m) { return 0; } -static int mount_fix_timeouts(Mount *m) { - MountParameters *p; - const char *timeout = NULL; - Unit *other; - Iterator i; - usec_t u; - char *t; - int r; - - assert(m); - - p = get_mount_parameters_fragment(m); - if (!p) - return 0; - - /* Allow configuration how long we wait for a device that - * backs a mount point to show up. This is useful to support - * endless device timeouts for devices that show up only after - * user input, like crypto devices. */ - - if ((timeout = mount_test_option(p->options, "comment=systemd.device-timeout"))) - timeout += 31; - else if ((timeout = mount_test_option(p->options, "x-systemd.device-timeout"))) - timeout += 25; - else - return 0; - - t = strndup(timeout, strcspn(timeout, ",;" WHITESPACE)); - if (!t) - return -ENOMEM; - - r = parse_sec(t, &u); - free(t); - - if (r < 0) { - log_warning_unit(UNIT(m)->id, - "Failed to parse timeout for %s, ignoring: %s", - m->where, timeout); - return r; - } - - SET_FOREACH(other, UNIT(m)->dependencies[UNIT_AFTER], i) { - if (other->type != UNIT_DEVICE) - continue; - - other->job_timeout = u; - } - - return 0; -} - static int mount_verify(Mount *m) { _cleanup_free_ char *e = NULL; bool b; @@ -556,10 +505,6 @@ static int mount_add_extras(Mount *m) { if (r < 0) return r; - r = mount_fix_timeouts(m); - if (r < 0) - return r; - if (u->default_dependencies) { r = mount_add_default_dependencies(m); if (r < 0) diff --git a/src/core/unit.c b/src/core/unit.c index 6e40bc6e9..bace69f46 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -51,6 +51,7 @@ #include "dbus.h" #include "execute.h" #include "virt.h" +#include "dropin.h" const UnitVTable * const unit_vtable[_UNIT_TYPE_MAX] = { [UNIT_SERVICE] = &service_vtable, @@ -2966,68 +2967,55 @@ ExecRuntime *unit_get_exec_runtime(Unit *u) { return *(ExecRuntime**) ((uint8_t*) u + offset); } -static int drop_in_file(Unit *u, UnitSetPropertiesMode mode, const char *name, char **_p, char **_q) { - _cleanup_free_ char *b = NULL; - char *p, *q; - int r; - - assert(u); - assert(name); - assert(_p); - assert(_q); - - b = xescape(name, "/."); - if (!b) - return -ENOMEM; - - if (!filename_is_safe(b)) - return -EINVAL; - +static int unit_drop_in_dir(Unit *u, UnitSetPropertiesMode mode, bool transient, char **dir) { if (u->manager->running_as == SYSTEMD_USER) { - _cleanup_free_ char *c = NULL; + int r; - r = user_config_home(&c); - if (r < 0) - return r; + r = user_config_home(dir); if (r == 0) return -ENOENT; + return r; + } - p = strjoin(c, "/", u->id, ".d", NULL); - } else if (mode == UNIT_PERSISTENT && !u->transient) - p = strjoin("/etc/systemd/system/", u->id, ".d", NULL); + if (mode == UNIT_PERSISTENT && !transient) + *dir = strdup("/etc/systemd/system"); else - p = strjoin("/run/systemd/system/", u->id, ".d", NULL); - if (!p) + *dir = strdup("/run/systemd/system"); + if (!*dir) return -ENOMEM; - q = strjoin(p, "/90-", b, ".conf", NULL); - if (!q) { - free(p); - return -ENOMEM; - } - - *_p = p; - *_q = q; return 0; } +static int unit_drop_in_file(Unit *u, + UnitSetPropertiesMode mode, const char *name, char **p, char **q) { + _cleanup_free_ char *dir = NULL; + int r; + + assert(u); + + r = unit_drop_in_dir(u, mode, u->transient, &dir); + if (r < 0) + return r; + + return drop_in_file(dir, u->id, name, p, q); +} + int unit_write_drop_in(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *data) { - _cleanup_free_ char *p = NULL, *q = NULL; + + _cleanup_free_ char *dir = NULL; int r; assert(u); - assert(name); - assert(data); if (!IN_SET(mode, UNIT_PERSISTENT, UNIT_RUNTIME)) return 0; - r = drop_in_file(u, mode, name, &p, &q); + r = unit_drop_in_dir(u, mode, u->transient, &dir); if (r < 0) return r; - mkdir_p(p, 0755); - return write_string_file_atomic_label(q, data); + return write_drop_in(dir, u->id, name, data); } int unit_write_drop_in_format(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *format, ...) { @@ -3103,7 +3091,7 @@ int unit_remove_drop_in(Unit *u, UnitSetPropertiesMode mode, const char *name) { if (!IN_SET(mode, UNIT_PERSISTENT, UNIT_RUNTIME)) return 0; - r = drop_in_file(u, mode, name, &p, &q); + r = unit_drop_in_file(u, mode, name, &p, &q); if (r < 0) return r; diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c index 98772fb56..6f392dfd4 100644 --- a/src/fstab-generator/fstab-generator.c +++ b/src/fstab-generator/fstab-generator.c @@ -44,6 +44,7 @@ static char *arg_root_fstype = NULL; static char *arg_root_options = NULL; static int arg_root_rw = -1; + static int mount_find_pri(struct mntent *me, int *ret) { char *end, *pri; unsigned long r; @@ -173,7 +174,8 @@ static int add_mount( _cleanup_free_ char *name = NULL, *unit = NULL, *lnk = NULL, - *automount_name = NULL, *automount_unit = NULL; + *automount_name = NULL, *automount_unit = NULL, + *filtered = NULL; _cleanup_fclose_ FILE *f = NULL; int r; @@ -245,8 +247,12 @@ static int add_mount( if (!isempty(fstype) && !streq(fstype, "auto")) fprintf(f, "Type=%s\n", fstype); - if (!isempty(opts) && !streq(opts, "defaults")) - fprintf(f, "Options=%s\n", opts); + r = generator_write_timeouts(arg_dest, what, where, opts, &filtered); + if (r < 0) + return r; + + if (!isempty(filtered) && !streq(filtered, "defaults")) + fprintf(f, "Options=%s\n", filtered); fflush(f); if (ferror(f)) { diff --git a/src/shared/dropin.c b/src/shared/dropin.c new file mode 100644 index 000000000..7774236f7 --- /dev/null +++ b/src/shared/dropin.c @@ -0,0 +1,98 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + This file is part of systemd. + + Copyright 2014 Zbigniew Jędrzejewski-Szmek + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include "dropin.h" +#include "util.h" +#include "mkdir.h" +#include "fileio-label.h" + +int drop_in_file(const char *dir, const char *unit, + const char *name, char **_p, char **_q) { + + _cleanup_free_ char *b = NULL; + char *p, *q; + + assert(unit); + assert(name); + assert(_p); + assert(_q); + + b = xescape(name, "/."); + if (!b) + return -ENOMEM; + + if (!filename_is_safe(b)) + return -EINVAL; + + p = strjoin(dir, "/", unit, ".d", NULL); + if (!p) + return -ENOMEM; + + q = strjoin(p, "/90-", b, ".conf", NULL); + if (!q) { + free(p); + return -ENOMEM; + } + + *_p = p; + *_q = q; + return 0; +} + +int write_drop_in(const char *dir, const char *unit, + const char *name, const char *data) { + + _cleanup_free_ char *p = NULL, *q = NULL; + int r; + + assert(dir); + assert(unit); + assert(name); + assert(data); + + r = drop_in_file(dir, unit, name, &p, &q); + if (r < 0) + return r; + + mkdir_p(p, 0755); + return write_string_file_atomic_label(q, data); +} + +int write_drop_in_format(const char *dir, const char *unit, + const char *name, const char *format, ...) { + _cleanup_free_ char *p = NULL; + va_list ap; + int r; + + assert(dir); + assert(unit); + assert(name); + assert(format); + + va_start(ap, format); + r = vasprintf(&p, format, ap); + va_end(ap); + + if (r < 0) + return -ENOMEM; + + return write_drop_in(dir, unit, name, p); +} diff --git a/src/shared/dropin.h b/src/shared/dropin.h new file mode 100644 index 000000000..295863296 --- /dev/null +++ b/src/shared/dropin.h @@ -0,0 +1,31 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +#pragma once + +/*** + This file is part of systemd. + + Copyright 2014 Zbigniew Jędrzejewski-Szmek + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +int drop_in_file(const char *dir, const char *unit, + const char *name, char **_p, char **_q); + +int write_drop_in(const char *dir, const char *unit, + const char *name, const char *data); + +int write_drop_in_format(const char *dir, const char *unit, + const char *name, const char *format, ...); diff --git a/src/shared/generator.c b/src/shared/generator.c index dcfddaa73..762033bbd 100644 --- a/src/shared/generator.c +++ b/src/shared/generator.c @@ -28,6 +28,7 @@ #include "unit-name.h" #include "generator.h" #include "path-util.h" +#include "dropin.h" int generator_write_fsck_deps( FILE *f, @@ -86,3 +87,59 @@ int generator_write_fsck_deps( return 0; } + +int generator_write_timeouts(const char *dir, const char *what, const char *where, + const char *opts, char **filtered) { + + /* Allow configuration how long we wait for a device that + * backs a mount point to show up. This is useful to support + * endless device timeouts for devices that show up only after + * user input, like crypto devices. */ + + _cleanup_free_ char *node = NULL, *unit = NULL, *t = NULL; + char *prefix, *start, *timeout, *postfix; + usec_t u; + int r; + size_t len; + + if ((start = mount_test_option(opts, "comment=systemd.device-timeout"))) + timeout = start + 31; + else if ((start = mount_test_option(opts, "x-systemd.device-timeout"))) + timeout = start + 25; + else { + *filtered = strdup(opts); + if (!*filtered) + return log_oom(); + + return 0; + } + + len = strcspn(timeout, ",;" WHITESPACE); + t = strndup(timeout, len); + if (!t) + return -ENOMEM; + + prefix = strndupa(opts, start - opts - (start != opts)); + postfix = timeout + len + (timeout[len] != '\0'); + *filtered = strjoin(prefix, *postfix ? postfix : NULL, NULL); + if (!*filtered) + return log_oom(); + + r = parse_sec(t, &u); + if (r < 0) { + log_warning("Failed to parse timeout for %s, ignoring: %s", + where, timeout); + return 0; + } + + node = fstab_node_to_udev_node(what); + if (!node) + return log_oom(); + + unit = unit_name_from_path(node, ".device"); + if (!unit) + return -ENOMEM; + + return write_drop_in_format(dir, unit, "device-timeout", + "[Unit]\nJobTimeoutSec=%u", u / USEC_PER_SEC); +} diff --git a/src/shared/generator.h b/src/shared/generator.h index 0140aa943..64bd28f59 100644 --- a/src/shared/generator.h +++ b/src/shared/generator.h @@ -24,3 +24,6 @@ #include int generator_write_fsck_deps(FILE *f, const char *dest, const char *what, const char *where, const char *type); + +int generator_write_timeouts(const char *dir, const char *what, const char *where, + const char *opts, char **filtered); diff --git a/src/shared/path-lookup.h b/src/shared/path-lookup.h index 847a52f20..4c77bee39 100644 --- a/src/shared/path-lookup.h +++ b/src/shared/path-lookup.h @@ -21,6 +21,8 @@ along with systemd; If not, see . ***/ +#include "macro.h" + typedef struct LookupPaths { char **unit_path; #ifdef HAVE_SYSV_COMPAT