|
|
626085 |
From a4c51f1bb38f272fb9c3dbaa33f1f383639ce345 Mon Sep 17 00:00:00 2001
|
|
|
626085 |
From: Colin Walters <walters@verbum.org>
|
|
|
626085 |
Date: Tue, 11 Jul 2017 12:48:57 -0400
|
|
|
626085 |
Subject: [PATCH] fstab-generator: Chase symlinks where possible (#6293)
|
|
|
626085 |
|
|
|
626085 |
This has a long history; see see 5261ba901845c084de5a8fd06500ed09bfb0bd80
|
|
|
626085 |
which originally introduced the behavior. Unfortunately that commit
|
|
|
626085 |
doesn't include any rationale, but IIRC the basic issue is that
|
|
|
626085 |
systemd wants to model the real mount state as units, and symlinks
|
|
|
626085 |
make canonicalization much more difficult.
|
|
|
626085 |
|
|
|
626085 |
At the same time, on a RHEL6 system (upstart), one can make e.g. `/home` a
|
|
|
626085 |
symlink, and things work as well as they always did; but one doesn't have
|
|
|
626085 |
access to the sophistication of mount units (dependencies, introspection, etc.)
|
|
|
626085 |
Supporting symlinks here will hence make it easier for people to do upgrades to
|
|
|
626085 |
RHEL7 and beyond.
|
|
|
626085 |
|
|
|
626085 |
The `/home` as symlink case also appears prominently for OSTree; see
|
|
|
626085 |
https://ostree.readthedocs.io/en/latest/manual/adapting-existing/
|
|
|
626085 |
|
|
|
626085 |
Further work has landed in the nspawn case for this; see e.g.
|
|
|
626085 |
d944dc9553009822deaddec76814f5642a6a8176
|
|
|
626085 |
|
|
|
626085 |
A basic limitation with doing this in the fstab generator (and that I hit while
|
|
|
626085 |
doing some testing) is that we obviously can't chase symlinks into mounts,
|
|
|
626085 |
since the generator runs early before mounts. Or at least - doing so would
|
|
|
626085 |
require multiple passes over the fstab data (as well as looking at existing
|
|
|
626085 |
mount units), and potentially doing multi-phase generation. I'm not sure it's
|
|
|
626085 |
worth doing that without a real world use case. For now, this will fix at least
|
|
|
626085 |
the OSTree + `/home` <https://bugzilla.redhat.com/show_bug.cgi?id=1382873> case
|
|
|
626085 |
mentioned above, and in general anyone who for whatever reason has symlinks in
|
|
|
626085 |
their `/etc/fstab`.
|
|
|
626085 |
|
|
|
626085 |
(cherry picked from commit 634735b56b82bdde3c67193ba7b470bab80fdcbd)
|
|
|
626085 |
|
|
|
626085 |
Resolves: RHEL-6223
|
|
|
626085 |
---
|
|
|
626085 |
man/systemd-fstab-generator.xml | 8 +++++
|
|
|
626085 |
man/systemd.mount.xml | 5 ++--
|
|
|
626085 |
src/fstab-generator/fstab-generator.c | 42 ++++++++++++++++++++++-----
|
|
|
626085 |
3 files changed, 45 insertions(+), 10 deletions(-)
|
|
|
626085 |
|
|
|
626085 |
diff --git a/man/systemd-fstab-generator.xml b/man/systemd-fstab-generator.xml
|
|
|
626085 |
index bdc2dc1d0e..6f45c680cc 100644
|
|
|
626085 |
--- a/man/systemd-fstab-generator.xml
|
|
|
626085 |
+++ b/man/systemd-fstab-generator.xml
|
|
|
626085 |
@@ -71,6 +71,14 @@
|
|
|
626085 |
for more information about special <filename>/etc/fstab</filename>
|
|
|
626085 |
mount options this generator understands.</para>
|
|
|
626085 |
|
|
|
626085 |
+ <para>One special topic is handling of symbolic links. Historical init
|
|
|
626085 |
+ implementations supported symlinks in <filename>/etc/fstab</filename>.
|
|
|
626085 |
+ Because mount units will refuse mounts where the target is a symbolic link,
|
|
|
626085 |
+ this generator will resolve any symlinks as far as possible when processing
|
|
|
626085 |
+ <filename>/etc/fstab</filename> in order to enhance backwards compatibility.
|
|
|
626085 |
+ If a symlink target does not exist at the time that this generator runs, it
|
|
|
626085 |
+ is assumed that the symlink target is the final target of the mount.</para>
|
|
|
626085 |
+
|
|
|
626085 |
<para><filename>systemd-fstab-generator</filename> implements
|
|
|
626085 |
<citerefentry><refentrytitle>systemd.generator</refentrytitle><manvolnum>7</manvolnum></citerefentry>.</para>
|
|
|
626085 |
</refsect1>
|
|
|
626085 |
diff --git a/man/systemd.mount.xml b/man/systemd.mount.xml
|
|
|
626085 |
index 1590c44cec..5021db5584 100644
|
|
|
626085 |
--- a/man/systemd.mount.xml
|
|
|
626085 |
+++ b/man/systemd.mount.xml
|
|
|
626085 |
@@ -295,8 +295,9 @@
|
|
|
626085 |
|
|
|
626085 |
<varlistentry>
|
|
|
626085 |
<term><varname>Where=</varname></term>
|
|
|
626085 |
- <listitem><para>Takes an absolute path of a directory of the
|
|
|
626085 |
- mount point. If the mount point does not exist at the time of
|
|
|
626085 |
+ <listitem><para>Takes an absolute path of a directory for the
|
|
|
626085 |
+ mount point; in particular, the destination cannot be a symbolic
|
|
|
626085 |
+ link. If the mount point does not exist at the time of
|
|
|
626085 |
mounting, it is created. This string must be reflected in the
|
|
|
626085 |
unit filename. (See above.) This option is
|
|
|
626085 |
mandatory.</para></listitem>
|
|
|
626085 |
diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c
|
|
|
626085 |
index 23b5457e43..91603b08f4 100644
|
|
|
626085 |
--- a/src/fstab-generator/fstab-generator.c
|
|
|
626085 |
+++ b/src/fstab-generator/fstab-generator.c
|
|
|
626085 |
@@ -240,6 +240,7 @@ static int write_idle_timeout(FILE *f, const char *where, const char *opts) {
|
|
|
626085 |
static int add_mount(
|
|
|
626085 |
const char *what,
|
|
|
626085 |
const char *where,
|
|
|
626085 |
+ const char *original_where,
|
|
|
626085 |
const char *fstype,
|
|
|
626085 |
const char *opts,
|
|
|
626085 |
int passno,
|
|
|
626085 |
@@ -327,12 +328,14 @@ static int add_mount(
|
|
|
626085 |
}
|
|
|
626085 |
|
|
|
626085 |
fprintf(f,
|
|
|
626085 |
- "\n"
|
|
|
626085 |
+ "\n"
|
|
|
626085 |
"[Mount]\n"
|
|
|
626085 |
- "What=%s\n"
|
|
|
626085 |
- "Where=%s\n",
|
|
|
626085 |
- what,
|
|
|
626085 |
- where);
|
|
|
626085 |
+ "What=%s\n",
|
|
|
626085 |
+ what);
|
|
|
626085 |
+
|
|
|
626085 |
+ if (original_where)
|
|
|
626085 |
+ fprintf(f, "# Canonicalized from %s\n", original_where);
|
|
|
626085 |
+ fprintf(f, "Where=%s\n", where);
|
|
|
626085 |
|
|
|
626085 |
if (!isempty(fstype) && !streq(fstype, "auto"))
|
|
|
626085 |
fprintf(f, "Type=%s\n", fstype);
|
|
|
626085 |
@@ -436,7 +439,7 @@ static int parse_fstab(bool initrd) {
|
|
|
626085 |
}
|
|
|
626085 |
|
|
|
626085 |
while ((me = getmntent(f))) {
|
|
|
626085 |
- _cleanup_free_ char *where = NULL, *what = NULL;
|
|
|
626085 |
+ _cleanup_free_ char *where = NULL, *what = NULL, *canonical_where = NULL;
|
|
|
626085 |
bool noauto, nofail;
|
|
|
626085 |
int k;
|
|
|
626085 |
|
|
|
626085 |
@@ -456,8 +459,28 @@ static int parse_fstab(bool initrd) {
|
|
|
626085 |
if (!where)
|
|
|
626085 |
return log_oom();
|
|
|
626085 |
|
|
|
626085 |
- if (is_path(where))
|
|
|
626085 |
+ if (is_path(where)) {
|
|
|
626085 |
path_kill_slashes(where);
|
|
|
626085 |
+ /* Follow symlinks here; see 5261ba901845c084de5a8fd06500ed09bfb0bd80 which makes sense for
|
|
|
626085 |
+ * mount units, but causes problems since it historically worked to have symlinks in e.g.
|
|
|
626085 |
+ * /etc/fstab. So we canonicalize here. Note that we use CHASE_NONEXISTENT to handle the case
|
|
|
626085 |
+ * where a symlink refers to another mount target; this works assuming the sub-mountpoint
|
|
|
626085 |
+ * target is the final directory.
|
|
|
626085 |
+ */
|
|
|
626085 |
+ r = chase_symlinks(where, initrd ? "/sysroot" : NULL,
|
|
|
626085 |
+ CHASE_PREFIX_ROOT | CHASE_NONEXISTENT,
|
|
|
626085 |
+ &canonical_where);
|
|
|
626085 |
+ if (r < 0)
|
|
|
626085 |
+ /* In this case for now we continue on as if it wasn't a symlink */
|
|
|
626085 |
+ log_warning_errno(r, "Failed to read symlink target for %s: %m", where);
|
|
|
626085 |
+ else {
|
|
|
626085 |
+ if (streq(canonical_where, where))
|
|
|
626085 |
+ canonical_where = mfree(canonical_where);
|
|
|
626085 |
+ else
|
|
|
626085 |
+ log_debug("Canonicalized what=%s where=%s to %s",
|
|
|
626085 |
+ what, where, canonical_where);
|
|
|
626085 |
+ }
|
|
|
626085 |
+ }
|
|
|
626085 |
|
|
|
626085 |
noauto = fstab_test_yes_no_option(me->mnt_opts, "noauto\0" "auto\0");
|
|
|
626085 |
nofail = fstab_test_yes_no_option(me->mnt_opts, "nofail\0" "fail\0");
|
|
|
626085 |
@@ -482,7 +505,8 @@ static int parse_fstab(bool initrd) {
|
|
|
626085 |
post = SPECIAL_LOCAL_FS_TARGET;
|
|
|
626085 |
|
|
|
626085 |
k = add_mount(what,
|
|
|
626085 |
- where,
|
|
|
626085 |
+ canonical_where ?: where,
|
|
|
626085 |
+ canonical_where ? where: NULL,
|
|
|
626085 |
me->mnt_type,
|
|
|
626085 |
me->mnt_opts,
|
|
|
626085 |
me->mnt_passno,
|
|
|
626085 |
@@ -526,6 +550,7 @@ static int add_sysroot_mount(void) {
|
|
|
626085 |
log_debug("Found entry what=%s where=/sysroot type=%s", what, strna(arg_root_fstype));
|
|
|
626085 |
return add_mount(what,
|
|
|
626085 |
"/sysroot",
|
|
|
626085 |
+ NULL,
|
|
|
626085 |
arg_root_fstype,
|
|
|
626085 |
opts,
|
|
|
626085 |
1,
|
|
|
626085 |
@@ -583,6 +608,7 @@ static int add_sysroot_usr_mount(void) {
|
|
|
626085 |
log_debug("Found entry what=%s where=/sysroot/usr type=%s", what, strna(arg_usr_fstype));
|
|
|
626085 |
return add_mount(what,
|
|
|
626085 |
"/sysroot/usr",
|
|
|
626085 |
+ NULL,
|
|
|
626085 |
arg_usr_fstype,
|
|
|
626085 |
opts,
|
|
|
626085 |
1,
|