fstab-generator: support for x-systemd.onfailure (#42440)
1. test-fstab-generator: fix inverted /mnt symlink guard The test-18-options.fstab.input scenario was guarded by a check that was always true on a normal system, so it was silently skipped and its fixtures had drifted out of sync with actual generator output. This commit fixes the guard and repairs the stale fixtures it exposed. 2. fstab-generator: support for x-systemd.onfailure Add support for the x-systemd.onfailure= fstab option in systemd-fstab-generator. This allows configuring OnFailure= dependencies for generated mount units directly through /etc/fstab. For example: /dev/sda1 /data ext4 defaults,x-systemd.onfailure=emergency.target 0 2 results in the generated mount unit containing: [Unit] OnFailure=emergency.target This makes it possible to attach recovery targets or services to mount failures directly from fstab configuration. Add documentation and generator tests.
This commit is contained in:
@@ -284,6 +284,25 @@
|
||||
<xi:include href="version-info.xml" xpointer="v220"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>x-systemd.onfailure=</option></term>
|
||||
|
||||
<listitem><para>In the created mount unit, configures an
|
||||
<varname>OnFailure=</varname> dependency. The argument is a unit name, see
|
||||
<option>x-systemd.requires=</option> above. This option may be specified more than
|
||||
once. See <varname>OnFailure=</varname> in
|
||||
<citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
||||
for details.</para>
|
||||
|
||||
<para>Note that this option always applies to the created mount
|
||||
unit only, regardless of whether <option>x-systemd.automount</option>
|
||||
has been specified.</para>
|
||||
|
||||
<para>Note that this option is silently ignored on swap entries.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v262"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>x-systemd.graceful-option=</option></term>
|
||||
|
||||
|
||||
@@ -341,6 +341,7 @@ static int write_dependency(
|
||||
const char *where,
|
||||
const char *opts,
|
||||
const char *filter,
|
||||
const char *suffix,
|
||||
const char* const *unit_settings) {
|
||||
|
||||
_cleanup_strv_free_ char **unit_names = NULL;
|
||||
@@ -360,7 +361,9 @@ static int write_dependency(
|
||||
STRV_FOREACH(s, unit_names) {
|
||||
_cleanup_free_ char *mangled = NULL;
|
||||
|
||||
r = unit_name_mangle_with_suffix(*s, "as dependency", 0, ".mount", &mangled);
|
||||
r = suffix ?
|
||||
unit_name_mangle_with_suffix(*s, "as dependency", 0, suffix, &mangled) :
|
||||
unit_name_mangle(*s, 0, &mangled);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to generate dependency unit name for '%s': %m", where);
|
||||
|
||||
@@ -376,22 +379,24 @@ static int write_dependency(
|
||||
|
||||
static int write_after(FILE *f, const char *where, const char *opts) {
|
||||
return write_dependency(f, where, opts,
|
||||
"x-systemd.after\0", STRV_MAKE_CONST("After"));
|
||||
"x-systemd.after\0", /* suffix= */ ".mount", STRV_MAKE_CONST("After"));
|
||||
}
|
||||
|
||||
static int write_requires_after(FILE *f, const char *where, const char *opts) {
|
||||
return write_dependency(f, where, opts,
|
||||
"x-systemd.requires\0", STRV_MAKE_CONST("Requires", "After"));
|
||||
"x-systemd.requires\0", /* suffix= */ ".mount",
|
||||
STRV_MAKE_CONST("Requires", "After"));
|
||||
}
|
||||
|
||||
static int write_wants_after(FILE *f, const char *where, const char *opts) {
|
||||
return write_dependency(f, where, opts,
|
||||
"x-systemd.wants\0", STRV_MAKE_CONST("Wants", "After"));
|
||||
"x-systemd.wants\0", /* suffix= */ ".mount",
|
||||
STRV_MAKE_CONST("Wants", "After"));
|
||||
}
|
||||
|
||||
static int write_before(FILE *f, const char *where, const char *opts) {
|
||||
return write_dependency(f, where, opts,
|
||||
"x-systemd.before\0", STRV_MAKE_CONST("Before"));
|
||||
"x-systemd.before\0", /* suffix= */ ".mount", STRV_MAKE_CONST("Before"));
|
||||
}
|
||||
|
||||
static int write_mounts_for(
|
||||
@@ -426,6 +431,11 @@ static int write_mounts_for(
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int write_on_failure(FILE *f, const char *where, const char *opts) {
|
||||
return write_dependency(f, where, opts,
|
||||
"x-systemd.onfailure\0", /* suffix= */ NULL, STRV_MAKE_CONST("OnFailure"));
|
||||
}
|
||||
|
||||
static int write_extra_dependencies(FILE *f, const char *where, const char *opts) {
|
||||
int r;
|
||||
|
||||
@@ -460,6 +470,10 @@ static int write_extra_dependencies(FILE *f, const char *where, const char *opts
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = write_on_failure(f, where, opts);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -67,15 +67,15 @@ test_one() (
|
||||
|
||||
# .deb packager seems to dislike files named with backslash. So, as a workaround, we store files
|
||||
# without backslash in .expected.
|
||||
for i in "$out"/**/*\\*.{mount,swap}; do
|
||||
for i in "$out"/**/*\\*.{mount,swap,automount}; do
|
||||
k="${i//\\/}"
|
||||
if [[ "$i" != "$k" ]]; then
|
||||
if [[ -f "$i" ]]; then
|
||||
mv "$i" "$k"
|
||||
elif [[ -L "$i" ]]; then
|
||||
if [[ -L "$i" ]]; then
|
||||
dest=$(readlink "$i")
|
||||
rm "$i"
|
||||
ln -s "${dest//\\/}" "$k"
|
||||
elif [[ -f "$i" ]]; then
|
||||
mv "$i" "$k"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
@@ -130,8 +130,7 @@ test_one() (
|
||||
for f in "$src"/test-*.input; do
|
||||
# If /mnt is a symlink, then the expected output from this
|
||||
# test scenario will not match the actual output
|
||||
if test "$f" = "$src/test-18-options.fstab.input" -a "$(readlink /mnt)" != "/mnt"
|
||||
then
|
||||
if [[ "$f" == "$src/test-18-options.fstab.input" && -L /mnt ]]; then
|
||||
echo "Skip $f because /mnt is a symlink"
|
||||
continue
|
||||
fi
|
||||
|
||||
-1
@@ -1 +0,0 @@
|
||||
../mnt-wantedby-automount.automount
|
||||
+1
@@ -0,0 +1 @@
|
||||
../mnt-wantedbyx2dautomount.automount
|
||||
+1
@@ -0,0 +1 @@
|
||||
../mnt-onfailure.mount
|
||||
+1
@@ -0,0 +1 @@
|
||||
../mnt-onfailuremulti.mount
|
||||
@@ -0,0 +1,13 @@
|
||||
# Automatically generated by systemd-fstab-generator
|
||||
|
||||
[Unit]
|
||||
Documentation=man:fstab(5) man:systemd-fstab-generator(8)
|
||||
SourcePath=/etc/fstab
|
||||
OnFailure=foo.service
|
||||
Before=local-fs.target
|
||||
After=blockdev@dev-sdx18.target
|
||||
|
||||
[Mount]
|
||||
What=/dev/sdx18
|
||||
Where=/mnt/onfailure
|
||||
Options=x-systemd.onfailure=foo.service
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
# Automatically generated by systemd-fstab-generator
|
||||
|
||||
[Unit]
|
||||
Documentation=man:fstab(5) man:systemd-fstab-generator(8)
|
||||
SourcePath=/etc/fstab
|
||||
OnFailure=foo.service bar.service
|
||||
Before=local-fs.target
|
||||
After=blockdev@dev-sdx19.target
|
||||
|
||||
[Mount]
|
||||
What=/dev/sdx19
|
||||
Where=/mnt/onfailuremulti
|
||||
Options=x-systemd.onfailure=foo.service,x-systemd.onfailure=bar.service
|
||||
@@ -3,8 +3,8 @@
|
||||
[Unit]
|
||||
Documentation=man:fstab(5) man:systemd-fstab-generator(8)
|
||||
SourcePath=/etc/fstab
|
||||
After=foo.service
|
||||
Requires=foo.service
|
||||
After=foo.service
|
||||
Before=local-fs.target
|
||||
After=blockdev@dev-sdx5.target
|
||||
|
||||
|
||||
+1
-1
@@ -10,5 +10,5 @@ After=blockdev@dev-sdx17.target
|
||||
|
||||
[Mount]
|
||||
What=/dev/sdx17
|
||||
Where=/mnt/wantedby
|
||||
Where=/mnt/wantedby-automount
|
||||
Options=x-systemd.wanted-by=foo.service,x-systemd.automount
|
||||
-1
@@ -1 +0,0 @@
|
||||
../mnt-wantedby-automount.automount
|
||||
+1
@@ -0,0 +1 @@
|
||||
../mnt-wantedbyx2dautomount.automount
|
||||
+1
@@ -0,0 +1 @@
|
||||
../mnt-onfailure.mount
|
||||
+1
@@ -0,0 +1 @@
|
||||
../mnt-onfailuremulti.mount
|
||||
@@ -0,0 +1,13 @@
|
||||
# Automatically generated by systemd-fstab-generator
|
||||
|
||||
[Unit]
|
||||
Documentation=man:fstab(5) man:systemd-fstab-generator(8)
|
||||
SourcePath=/etc/fstab
|
||||
OnFailure=foo.service
|
||||
Before=local-fs.target
|
||||
After=blockdev@dev-sdx18.target
|
||||
|
||||
[Mount]
|
||||
What=/dev/sdx18
|
||||
Where=/mnt/onfailure
|
||||
Options=x-systemd.onfailure=foo.service
|
||||
@@ -0,0 +1,13 @@
|
||||
# Automatically generated by systemd-fstab-generator
|
||||
|
||||
[Unit]
|
||||
Documentation=man:fstab(5) man:systemd-fstab-generator(8)
|
||||
SourcePath=/etc/fstab
|
||||
OnFailure=foo.service bar.service
|
||||
Before=local-fs.target
|
||||
After=blockdev@dev-sdx19.target
|
||||
|
||||
[Mount]
|
||||
What=/dev/sdx19
|
||||
Where=/mnt/onfailuremulti
|
||||
Options=x-systemd.onfailure=foo.service,x-systemd.onfailure=bar.service
|
||||
@@ -3,8 +3,8 @@
|
||||
[Unit]
|
||||
Documentation=man:fstab(5) man:systemd-fstab-generator(8)
|
||||
SourcePath=/etc/fstab
|
||||
After=foo.service
|
||||
Requires=foo.service
|
||||
After=foo.service
|
||||
Before=local-fs.target
|
||||
After=blockdev@dev-sdx5.target
|
||||
|
||||
|
||||
+1
-1
@@ -10,5 +10,5 @@ After=blockdev@dev-sdx17.target
|
||||
|
||||
[Mount]
|
||||
What=/dev/sdx17
|
||||
Where=/mnt/wantedby
|
||||
Where=/mnt/wantedby-automount
|
||||
Options=x-systemd.wanted-by=foo.service,x-systemd.automount
|
||||
@@ -15,3 +15,5 @@
|
||||
/dev/sdx15 /mnt/noauto auto noauto 0 0
|
||||
/dev/sdx16 /mnt/nofail auto nofail 0 0
|
||||
/dev/sdx17 /mnt/wantedby-automount auto x-systemd.wanted-by=foo.service,x-systemd.automount 0 0
|
||||
/dev/sdx18 /mnt/onfailure auto x-systemd.onfailure=foo.service 0 0
|
||||
/dev/sdx19 /mnt/onfailuremulti auto x-systemd.onfailure=foo.service,x-systemd.onfailure=bar.service 0 0
|
||||
|
||||
Reference in New Issue
Block a user