|
|
1ff636 |
From 8f149756435998d009a8edc7206c5de038e5cbf1 Mon Sep 17 00:00:00 2001
|
|
|
1ff636 |
From: Karel Zak <kzak@redhat.com>
|
|
|
1ff636 |
Date: Mon, 18 May 2015 12:30:37 +0200
|
|
|
1ff636 |
Subject: [PATCH] fstab-generator: add x-systemd.requires and
|
|
|
1ff636 |
x-systemd.requires-mounts-for
|
|
|
1ff636 |
|
|
|
1ff636 |
Currently we have no way how to specify dependencies between fstab
|
|
|
1ff636 |
entries (or another units) in the /etc/fstab. It means that users are
|
|
|
1ff636 |
forced to bypass fstab and write .mount units manually.
|
|
|
1ff636 |
|
|
|
1ff636 |
The patch introduces new systemd fstab options:
|
|
|
1ff636 |
|
|
|
1ff636 |
x-systemd.requires=<PATH>
|
|
|
1ff636 |
|
|
|
1ff636 |
- to specify dependence an another mount (PATH is translated to unit name)
|
|
|
1ff636 |
|
|
|
1ff636 |
x-systemd.requires=<UNIT>
|
|
|
1ff636 |
|
|
|
1ff636 |
- to specify dependence on arbitrary UNIT
|
|
|
1ff636 |
|
|
|
1ff636 |
x-systemd.requires-mounts-for=<PATH ...>
|
|
|
1ff636 |
|
|
|
1ff636 |
- to specify dependence on another paths, implemented by
|
|
|
1ff636 |
RequiresMountsFor=. The option may be specified more than once.
|
|
|
1ff636 |
|
|
|
1ff636 |
For example two bind mounts where B depends on A:
|
|
|
1ff636 |
|
|
|
1ff636 |
/mnt/test/A /mnt/test/A none bind,defaults
|
|
|
1ff636 |
/mnt/test/A /mnt/test/B none bind,x-systemd.requires=/mnt/test/A
|
|
|
1ff636 |
|
|
|
1ff636 |
More complex example with overlay FS where one mount point depends on
|
|
|
1ff636 |
"low" and "upper" directories:
|
|
|
1ff636 |
|
|
|
1ff636 |
/dev/sdc1 /mnt/low ext4 defaults
|
|
|
1ff636 |
/dev/sdc2 /mnt/high ext4 defaults
|
|
|
1ff636 |
overlay /mnt/merged overlay lowerdir=/mnt/low,upperdir=/mnt/high/data,workdir=/mnt/high/work,x-systemd.requires-mounts-for=/mnt/low,x-systemd.requires-mounts-for=mnt/high
|
|
|
1ff636 |
|
|
|
1ff636 |
https://bugzilla.redhat.com/show_bug.cgi?id=812826
|
|
|
1ff636 |
https://bugzilla.redhat.com/show_bug.cgi?id=1164334
|
|
|
1ff636 |
|
|
|
1ff636 |
Conflicts:
|
|
|
1ff636 |
src/fstab-generator/fstab-generator.c
|
|
|
1ff636 |
|
|
|
1ff636 |
Cherry-picked from: 3519d230c8bafe834b2dac26ace49fcfba139823
|
|
|
1ff636 |
Resolves: #1164334
|
|
|
1ff636 |
---
|
|
|
1ff636 |
man/systemd.mount.xml | 30 ++++++++++++++
|
|
|
1ff636 |
src/fstab-generator/fstab-generator.c | 76 +++++++++++++++++++++++++++++++++++
|
|
|
1ff636 |
src/shared/fstab-util.c | 30 ++++++++++++++
|
|
|
1ff636 |
src/shared/fstab-util.h | 2 +
|
|
|
1ff636 |
4 files changed, 138 insertions(+)
|
|
|
1ff636 |
|
|
|
1ff636 |
diff --git a/man/systemd.mount.xml b/man/systemd.mount.xml
|
|
|
1ff636 |
index fcb9a44..8e652e1 100644
|
|
|
1ff636 |
--- a/man/systemd.mount.xml
|
|
|
1ff636 |
+++ b/man/systemd.mount.xml
|
|
|
1ff636 |
@@ -139,6 +139,36 @@
|
|
|
1ff636 |
<variablelist class='fstab-options'>
|
|
|
1ff636 |
|
|
|
1ff636 |
<varlistentry>
|
|
|
1ff636 |
+ <term><option>x-systemd.requires=</option></term>
|
|
|
1ff636 |
+
|
|
|
1ff636 |
+ <listitem><para>Configures a <varname>Requires=</varname> and
|
|
|
1ff636 |
+ an <varname>After=</varname> dependency between the created
|
|
|
1ff636 |
+ mount unit and another systemd unit, such as a device or mount
|
|
|
1ff636 |
+ unit. The argument should be a unit name, or an absolute path
|
|
|
1ff636 |
+ to a device node or mount point. This option may be specified
|
|
|
1ff636 |
+ more than once. This option is particularly useful for mount
|
|
|
1ff636 |
+ point declarations that need an additional device to be around
|
|
|
1ff636 |
+ (such as an external journal device for journal file systems)
|
|
|
1ff636 |
+ or an additional mount to be in place (such as an overlay file
|
|
|
1ff636 |
+ system that merges multiple mount points). See
|
|
|
1ff636 |
+ <varname>After=</varname> and <varname>Requires=</varname> in
|
|
|
1ff636 |
+ <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
|
|
1ff636 |
+ for details.</para></listitem>
|
|
|
1ff636 |
+ </varlistentry>
|
|
|
1ff636 |
+
|
|
|
1ff636 |
+ <varlistentry>
|
|
|
1ff636 |
+ <term><option>x-systemd.requires-mounts-for=</option></term>
|
|
|
1ff636 |
+
|
|
|
1ff636 |
+ <listitem><para>Configures a
|
|
|
1ff636 |
+ <varname>RequiresMountsFor=</varname> dependency between the
|
|
|
1ff636 |
+ created mount unit and other mount units. The argument must be
|
|
|
1ff636 |
+ an absolute path. This option may be specified more than once.
|
|
|
1ff636 |
+ See <varname>RequiresMountsFor=</varname> in
|
|
|
1ff636 |
+ <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
|
|
1ff636 |
+ for details.</para></listitem>
|
|
|
1ff636 |
+ </varlistentry>
|
|
|
1ff636 |
+
|
|
|
1ff636 |
+ <varlistentry>
|
|
|
1ff636 |
<term><option>x-systemd.automount</option></term>
|
|
|
1ff636 |
|
|
|
1ff636 |
<listitem><para>An automount unit will be created for the file
|
|
|
1ff636 |
diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c
|
|
|
1ff636 |
index 8e2f522..65ed205 100644
|
|
|
1ff636 |
--- a/src/fstab-generator/fstab-generator.c
|
|
|
1ff636 |
+++ b/src/fstab-generator/fstab-generator.c
|
|
|
1ff636 |
@@ -155,6 +155,64 @@ static bool mount_in_initrd(struct mntent *me) {
|
|
|
1ff636 |
streq(me->mnt_dir, "/usr");
|
|
|
1ff636 |
}
|
|
|
1ff636 |
|
|
|
1ff636 |
+static int write_requires_after(FILE *f, const char *opts) {
|
|
|
1ff636 |
+ _cleanup_strv_free_ char **names = NULL, **units = NULL;
|
|
|
1ff636 |
+ _cleanup_free_ char *res = NULL;
|
|
|
1ff636 |
+ char **s;
|
|
|
1ff636 |
+ int r;
|
|
|
1ff636 |
+
|
|
|
1ff636 |
+ assert(f);
|
|
|
1ff636 |
+ assert(opts);
|
|
|
1ff636 |
+
|
|
|
1ff636 |
+ r = fstab_extract_values(opts, "x-systemd.requires", &names);
|
|
|
1ff636 |
+ if (r < 0)
|
|
|
1ff636 |
+ return log_warning_errno(r, "Failed to parse options: %m");
|
|
|
1ff636 |
+ if (r == 0)
|
|
|
1ff636 |
+ return 0;
|
|
|
1ff636 |
+
|
|
|
1ff636 |
+ STRV_FOREACH(s, names) {
|
|
|
1ff636 |
+ char *x;
|
|
|
1ff636 |
+
|
|
|
1ff636 |
+ x = unit_name_mangle_with_suffix(*s, MANGLE_NOGLOB, ".mount");
|
|
|
1ff636 |
+ if (!x)
|
|
|
1ff636 |
+ return log_error_errno(r, "Failed to generate unit name: %m");
|
|
|
1ff636 |
+ r = strv_consume(&units, x);
|
|
|
1ff636 |
+ if (r < 0)
|
|
|
1ff636 |
+ return log_oom();
|
|
|
1ff636 |
+ }
|
|
|
1ff636 |
+
|
|
|
1ff636 |
+ if (units) {
|
|
|
1ff636 |
+ res = strv_join(units, " ");
|
|
|
1ff636 |
+ if (!res)
|
|
|
1ff636 |
+ return log_oom();
|
|
|
1ff636 |
+ fprintf(f, "After=%1$s\nRequires=%1$s\n", res);
|
|
|
1ff636 |
+ }
|
|
|
1ff636 |
+
|
|
|
1ff636 |
+ return 0;
|
|
|
1ff636 |
+}
|
|
|
1ff636 |
+
|
|
|
1ff636 |
+static int write_requires_mounts_for(FILE *f, const char *opts) {
|
|
|
1ff636 |
+ _cleanup_strv_free_ char **paths = NULL;
|
|
|
1ff636 |
+ _cleanup_free_ char *res = NULL;
|
|
|
1ff636 |
+ int r;
|
|
|
1ff636 |
+
|
|
|
1ff636 |
+ assert(f);
|
|
|
1ff636 |
+ assert(opts);
|
|
|
1ff636 |
+
|
|
|
1ff636 |
+ r = fstab_extract_values(opts, "x-systemd.requires-mounts-for", &paths);
|
|
|
1ff636 |
+ if (r < 0)
|
|
|
1ff636 |
+ return log_warning_errno(r, "Failed to parse options: %m");
|
|
|
1ff636 |
+ if (r == 0)
|
|
|
1ff636 |
+ return 0;
|
|
|
1ff636 |
+
|
|
|
1ff636 |
+ res = strv_join(paths, " ");
|
|
|
1ff636 |
+ if (!res)
|
|
|
1ff636 |
+ return log_oom();
|
|
|
1ff636 |
+
|
|
|
1ff636 |
+ fprintf(f, "RequiresMountsFor=%s\n", res);
|
|
|
1ff636 |
+
|
|
|
1ff636 |
+ return 0;
|
|
|
1ff636 |
+}
|
|
|
1ff636 |
static int add_mount(
|
|
|
1ff636 |
const char *what,
|
|
|
1ff636 |
const char *where,
|
|
|
1ff636 |
@@ -225,6 +283,15 @@ static int add_mount(
|
|
|
1ff636 |
if (post && !noauto && !nofail && !automount)
|
|
|
1ff636 |
fprintf(f, "Before=%s\n", post);
|
|
|
1ff636 |
|
|
|
1ff636 |
+ if (!automount && opts) {
|
|
|
1ff636 |
+ r = write_requires_after(f, opts);
|
|
|
1ff636 |
+ if (r < 0)
|
|
|
1ff636 |
+ return r;
|
|
|
1ff636 |
+ r = write_requires_mounts_for(f, opts);
|
|
|
1ff636 |
+ if (r < 0)
|
|
|
1ff636 |
+ return r;
|
|
|
1ff636 |
+ }
|
|
|
1ff636 |
+
|
|
|
1ff636 |
if (passno != 0) {
|
|
|
1ff636 |
r = generator_write_fsck_deps(f, arg_dest, what, where, fstype);
|
|
|
1ff636 |
if (r < 0)
|
|
|
1ff636 |
@@ -289,6 +356,15 @@ static int add_mount(
|
|
|
1ff636 |
"Before=%s\n",
|
|
|
1ff636 |
post);
|
|
|
1ff636 |
|
|
|
1ff636 |
+ if (opts) {
|
|
|
1ff636 |
+ r = write_requires_after(f, opts);
|
|
|
1ff636 |
+ if (r < 0)
|
|
|
1ff636 |
+ return r;
|
|
|
1ff636 |
+ r = write_requires_mounts_for(f, opts);
|
|
|
1ff636 |
+ if (r < 0)
|
|
|
1ff636 |
+ return r;
|
|
|
1ff636 |
+ }
|
|
|
1ff636 |
+
|
|
|
1ff636 |
fprintf(f,
|
|
|
1ff636 |
"[Automount]\n"
|
|
|
1ff636 |
"Where=%s\n",
|
|
|
1ff636 |
diff --git a/src/shared/fstab-util.c b/src/shared/fstab-util.c
|
|
|
1ff636 |
index cf317e1..e231a0f 100644
|
|
|
1ff636 |
--- a/src/shared/fstab-util.c
|
|
|
1ff636 |
+++ b/src/shared/fstab-util.c
|
|
|
1ff636 |
@@ -125,6 +125,36 @@ answer:
|
|
|
1ff636 |
return !!n;
|
|
|
1ff636 |
}
|
|
|
1ff636 |
|
|
|
1ff636 |
+int fstab_extract_values(const char *opts, const char *name, char ***values) {
|
|
|
1ff636 |
+ _cleanup_strv_free_ char **optsv = NULL, **res = NULL;
|
|
|
1ff636 |
+ char **s;
|
|
|
1ff636 |
+
|
|
|
1ff636 |
+ assert(opts);
|
|
|
1ff636 |
+ assert(name);
|
|
|
1ff636 |
+ assert(values);
|
|
|
1ff636 |
+
|
|
|
1ff636 |
+ optsv = strv_split(opts, ",");
|
|
|
1ff636 |
+ if (!optsv)
|
|
|
1ff636 |
+ return -ENOMEM;
|
|
|
1ff636 |
+
|
|
|
1ff636 |
+ STRV_FOREACH(s, optsv) {
|
|
|
1ff636 |
+ char *arg;
|
|
|
1ff636 |
+ int r;
|
|
|
1ff636 |
+
|
|
|
1ff636 |
+ arg = startswith(*s, name);
|
|
|
1ff636 |
+ if (!arg || *arg != '=')
|
|
|
1ff636 |
+ continue;
|
|
|
1ff636 |
+ r = strv_extend(&res, arg + 1);
|
|
|
1ff636 |
+ if (r < 0)
|
|
|
1ff636 |
+ return r;
|
|
|
1ff636 |
+ }
|
|
|
1ff636 |
+
|
|
|
1ff636 |
+ *values = res;
|
|
|
1ff636 |
+ res = NULL;
|
|
|
1ff636 |
+
|
|
|
1ff636 |
+ return !!*values;
|
|
|
1ff636 |
+}
|
|
|
1ff636 |
+
|
|
|
1ff636 |
int fstab_find_pri(const char *options, int *ret) {
|
|
|
1ff636 |
_cleanup_free_ char *opt = NULL;
|
|
|
1ff636 |
int r;
|
|
|
1ff636 |
diff --git a/src/shared/fstab-util.h b/src/shared/fstab-util.h
|
|
|
1ff636 |
index 9f6b32e..387c562 100644
|
|
|
1ff636 |
--- a/src/shared/fstab-util.h
|
|
|
1ff636 |
+++ b/src/shared/fstab-util.h
|
|
|
1ff636 |
@@ -28,6 +28,8 @@
|
|
|
1ff636 |
int fstab_filter_options(const char *opts, const char *names,
|
|
|
1ff636 |
const char **namefound, char **value, char **filtered);
|
|
|
1ff636 |
|
|
|
1ff636 |
+int fstab_extract_values(const char *opts, const char *name, char ***values);
|
|
|
1ff636 |
+
|
|
|
1ff636 |
static inline bool fstab_test_option(const char *opts, const char *names) {
|
|
|
1ff636 |
return !!fstab_filter_options(opts, names, NULL, NULL, NULL);
|
|
|
1ff636 |
}
|