[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