[systemd-devel] [PATCH 1/3] Move x-systemd-device.timeout handling from core to fstab-generator
Zbigniew Jędrzejewski-Szmek
zbyszek at in.waw.pl
Fri Jun 27 21:00:40 PDT 2014
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.
---
Makefile.am | 8 +--
src/core/mount.c | 55 --------------------
src/core/unit.c | 70 +++++++++++--------------
src/fstab-generator/fstab-generator.c | 12 +++--
src/shared/dropin.c | 98 +++++++++++++++++++++++++++++++++++
src/shared/dropin.h | 31 +++++++++++
src/shared/generator.c | 57 ++++++++++++++++++++
src/shared/generator.h | 3 ++
src/shared/path-lookup.h | 2 +
9 files changed, 234 insertions(+), 102 deletions(-)
create mode 100644 src/shared/dropin.c
create mode 100644 src/shared/dropin.h
diff --git Makefile.am Makefile.am
index a7f44a4300..bfb1d4251c 100644
--- Makefile.am
+++ Makefile.am
@@ -814,8 +814,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 \
@@ -872,7 +870,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 src/core/mount.c src/core/mount.c
index aea2ab17c9..102bbef91b 100644
--- src/core/mount.c
+++ 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 src/core/unit.c src/core/unit.c
index 6e40bc6e9f..bace69f46a 100644
--- src/core/unit.c
+++ 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 src/fstab-generator/fstab-generator.c src/fstab-generator/fstab-generator.c
index 98772fb56b..6f392dfd4d 100644
--- src/fstab-generator/fstab-generator.c
+++ 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 src/shared/dropin.c src/shared/dropin.c
new file mode 100644
index 0000000000..7774236f71
--- /dev/null
+++ 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 <http://www.gnu.org/licenses/>.
+***/
+
+#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 src/shared/dropin.h src/shared/dropin.h
new file mode 100644
index 0000000000..2958632963
--- /dev/null
+++ 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 <http://www.gnu.org/licenses/>.
+***/
+
+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 src/shared/generator.c src/shared/generator.c
index dcfddaa731..762033bbdf 100644
--- src/shared/generator.c
+++ 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 src/shared/generator.h src/shared/generator.h
index 0140aa943f..64bd28f596 100644
--- src/shared/generator.h
+++ src/shared/generator.h
@@ -24,3 +24,6 @@
#include <stdio.h>
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 src/shared/path-lookup.h src/shared/path-lookup.h
index 847a52f20a..4c77bee393 100644
--- src/shared/path-lookup.h
+++ src/shared/path-lookup.h
@@ -21,6 +21,8 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "macro.h"
+
typedef struct LookupPaths {
char **unit_path;
#ifdef HAVE_SYSV_COMPAT
--
2.0.0
More information about the systemd-devel
mailing list