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.
This commit is contained in:
Zbigniew Jędrzejewski-Szmek 2014-06-27 12:12:07 -04:00
parent 6e81b5b9dc
commit 2968644080
9 changed files with 237 additions and 105 deletions

View File

@ -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) \

View File

@ -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)

View File

@ -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;
p = strjoin(c, "/", u->id, ".d", NULL);
} else if (mode == UNIT_PERSISTENT && !u->transient)
p = strjoin("/etc/systemd/system/", u->id, ".d", NULL);
else
p = strjoin("/run/systemd/system/", u->id, ".d", NULL);
if (!p)
return -ENOMEM;
q = strjoin(p, "/90-", b, ".conf", NULL);
if (!q) {
free(p);
return -ENOMEM;
return r;
}
*_p = p;
*_q = q;
if (mode == UNIT_PERSISTENT && !transient)
*dir = strdup("/etc/systemd/system");
else
*dir = strdup("/run/systemd/system");
if (!*dir)
return -ENOMEM;
return 0;
}
int unit_write_drop_in(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *data) {
_cleanup_free_ char *p = NULL, *q = NULL;
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 *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;

View File

@ -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)) {

98
src/shared/dropin.c Normal file
View File

@ -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);
}

31
src/shared/dropin.h Normal file
View File

@ -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, ...);

View File

@ -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);
}

View File

@ -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);

View File

@ -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