fstab-generator: support for x-systemd.onfailure

Add support for the x-systemd.onfailure fstab option in fstab-generator.

This allows generated mount units to include the systemd OnFailure=
dependency specified through /etc/fstab.

x-systemd.onfailure= is handled by generalizing the existing
write_dependency() helper (already used for After=/Before=/Requires=/
Wants=) to take an optional unit-name suffix. When no suffix is given,
unit names are mangled without forcing a ".mount" suffix, since
OnFailure= targets are not necessarily mount units. write_on_failure()
is now a thin wrapper around write_dependency().

Example:

/dev/sda1 /data ext4 defaults,x-systemd.onfailure=emergency.target 0 2

generates:

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:
nikhilnrr
2026-09-22 18:48:23 +02:00
committed by Luca Boccassi
parent 9d27286214
commit b7041b73cf
11 changed files with 96 additions and 5 deletions
+19
View File
@@ -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>
+19 -5
View File
@@ -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;
}
@@ -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
@@ -0,0 +1 @@
../mnt-onfailure.mount
@@ -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
@@ -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