Skip to content

Commit

Permalink
fstab-generator: if usr= is specified, mount it to /sysusr/usr/ first
Browse files Browse the repository at this point in the history
This changes the fstab-generator to handle mounting of /usr/ a bit
differently than before. Instead of immediately mounting the fs to
/sysroot/usr/ we'll first mount it to /sysusr/usr/ and then add a
separate bind mount that mounts it from /sysusr/usr/ to /sysroot/usr/.

This way we can access /usr independently of the root fs, without for
waiting to be mounted via the /sysusr/ hierarchy. This is useful for
invoking systemd-repart while a root fs doesn't exist yet and for
creating it, with partition data read from the /usr/ hierarchy.

This introduces a new generic target initrd-usr-fs.target that may be
used to generically order services against /sysusr/ to become available.
  • Loading branch information
poettering committed Apr 20, 2021
1 parent ee7561d commit 29a24ab
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 17 deletions.
1 change: 1 addition & 0 deletions src/basic/special.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#define SPECIAL_INITRD_FS_TARGET "initrd-fs.target"
#define SPECIAL_INITRD_ROOT_DEVICE_TARGET "initrd-root-device.target"
#define SPECIAL_INITRD_ROOT_FS_TARGET "initrd-root-fs.target"
#define SPECIAL_INITRD_USR_FS_TARGET "initrd-usr-fs.target"
#define SPECIAL_REMOTE_FS_TARGET "remote-fs.target" /* LSB's $remote_fs */
#define SPECIAL_REMOTE_FS_PRE_TARGET "remote-fs-pre.target"
#define SPECIAL_SWAP_TARGET "swap.target"
Expand Down
90 changes: 77 additions & 13 deletions src/fstab-generator/fstab-generator.c
Original file line number Diff line number Diff line change
Expand Up @@ -744,6 +744,10 @@ static int add_sysroot_mount(void) {
static int add_sysroot_usr_mount(void) {
_cleanup_free_ char *what = NULL;
const char *opts;
int r;

/* Returns 0 if we didn't do anything, > 0 if we either generated a unit for the /usr/ mount, or we
* know for sure something else did */

if (!arg_usr_what && !arg_usr_fstype && !arg_usr_options)
return 0;
Expand All @@ -767,8 +771,23 @@ static int add_sysroot_usr_mount(void) {
return log_oom();
}

if (!arg_usr_what)
if (isempty(arg_usr_what)) {
log_debug("Could not find a usr= entry on the kernel command line.");
return 0;
}

if (streq(arg_usr_what, "gpt-auto")) {
/* This is handled by the gpt-auto generator */
log_debug("Skipping /usr/ directory handling, as gpt-auto was requested.");
return 1; /* systemd-gpt-auto-generator will generate a unit for this, hence report that a
* unit file is being created for the host /usr/ mount. */
}

if (path_equal(arg_usr_what, "/dev/nfs")) {
/* This is handled by the initrd (if at all supported, that is) */
log_debug("Skipping /usr/ directory handling, as /dev/nfs was requested.");
return 1; /* As above, report that NFS code will create the unit */
}

what = fstab_node_to_udev_node(arg_usr_what);
if (!what)
Expand All @@ -781,17 +800,62 @@ static int add_sysroot_usr_mount(void) {
else
opts = arg_usr_options;

log_debug("Found entry what=%s where=/sysroot/usr type=%s", what, strna(arg_usr_fstype));
return add_mount(arg_dest,
what,
"/sysroot/usr",
NULL,
arg_usr_fstype,
opts,
is_device_path(what) ? 1 : 0, /* passno */
0,
SPECIAL_INITRD_FS_TARGET,
"/proc/cmdline");
/* When mounting /usr from the initrd, we add an extra level of indirection: we first mount the /usr/
* partition to /sysusr/usr/, and then afterwards bind mount that to /sysroot/usr/. We do this so
* that we can cover for systems that initially only have a /usr/ around and where the root fs needs
* to be synthesized, based on configuration included in /usr/, e.g. systemd-repart. Software like
* this should order itself after initrd-usr-fs.target and before initrd-fs.target; and it should
* look into both /sysusr/ and /sysroot/ for the configuration data to apply. */

log_debug("Found entry what=%s where=/sysusr/usr type=%s opts=%s", what, strna(arg_usr_fstype), strempty(opts));

r = add_mount(arg_dest,
what,
"/sysusr/usr",
NULL,
arg_usr_fstype,
opts,
is_device_path(what) ? 1 : 0, /* passno */
0,
SPECIAL_INITRD_USR_FS_TARGET,
"/proc/cmdline");
if (r < 0)
return r;

log_debug("Synthesizing entry what=/sysusr/usr where=/sysrootr/usr opts=bind");

r = add_mount(arg_dest,
"/sysusr/usr",
"/sysroot/usr",
NULL,
NULL,
"bind",
0,
0,
SPECIAL_INITRD_FS_TARGET,
"/proc/cmdline");
if (r < 0)
return r;

return 1;
}

static int add_sysroot_usr_mount_or_fallback(void) {
int r;

r = add_sysroot_usr_mount();
if (r != 0)
return r;

/* OK, so we didn't write anything out for /sysusr/usr/ nor /sysroot/usr/. In this case, let's make
* sure that initrd-usr-fs.target is at least ordered after sysroot.mount so that services that order
* themselves get the guarantee that /usr/ is definitely mounted somewhere. */

return generator_add_symlink(
arg_dest,
SPECIAL_INITRD_USR_FS_TARGET,
"requires",
"sysroot.mount");
}

static int add_volatile_root(void) {
Expand Down Expand Up @@ -953,7 +1017,7 @@ static int run(const char *dest, const char *dest_early, const char *dest_late)
if (in_initrd()) {
r = add_sysroot_mount();

r2 = add_sysroot_usr_mount();
r2 = add_sysroot_usr_mount_or_fallback();

r3 = add_volatile_root();
} else
Expand Down
17 changes: 17 additions & 0 deletions units/initrd-usr-fs.target
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
#
# This file is part of systemd.
#
# 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.

[Unit]
Description=Initrd /usr File System
Documentation=man:systemd.special(7)
AssertPathExists=/etc/initrd-release
OnFailure=emergency.target
OnFailureJobMode=replace-irreversibly
DefaultDependencies=no
Conflicts=shutdown.target
4 changes: 2 additions & 2 deletions units/initrd.target
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@ OnFailure=emergency.target
OnFailureJobMode=replace-irreversibly
AssertPathExists=/etc/initrd-release
Requires=basic.target
Wants=initrd-root-fs.target initrd-root-device.target initrd-fs.target initrd-parse-etc.service
After=initrd-root-fs.target initrd-root-device.target initrd-fs.target basic.target rescue.service rescue.target
Wants=initrd-root-fs.target initrd-root-device.target initrd-fs.target initrd-usr-fs.target initrd-parse-etc.service
After=initrd-root-fs.target initrd-root-device.target initrd-fs.target initrd-usr-fs.target basic.target rescue.service rescue.target
AllowIsolate=yes
1 change: 1 addition & 0 deletions units/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ units = [
['initrd-switch-root.service', 'ENABLE_INITRD'],
['initrd-switch-root.target', 'ENABLE_INITRD'],
['initrd-udevadm-cleanup-db.service', 'ENABLE_INITRD'],
['initrd-usr-fs.target', 'ENABLE_INITRD'],
['initrd.target', 'ENABLE_INITRD'],
['kexec.target', ''],
['ldconfig.service', 'ENABLE_LDCONFIG',
Expand Down
2 changes: 1 addition & 1 deletion units/systemd-repart.service.in
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Description=Repartition Root Disk
Documentation=man:systemd-repart.service(8)
DefaultDependencies=no
Conflicts=shutdown.target
After=sysroot.mount
After=initrd-usr-fs.target
Before=initrd-root-fs.target shutdown.target
ConditionVirtualization=!container
ConditionDirectoryNotEmpty=|/usr/lib/repart.d
Expand Down
2 changes: 1 addition & 1 deletion units/systemd-volatile-root.service.in
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Description=Enforce Volatile Root File Systems
Documentation=man:systemd-volatile-root.service(8)
DefaultDependencies=no
Conflicts=shutdown.target
After=sysroot.mount systemd-repart.service
After=sysroot.mount sysroot-usr.mount systemd-repart.service
Before=initrd-root-fs.target shutdown.target
AssertPathExists=/etc/initrd-release

Expand Down

0 comments on commit 29a24ab

Please sign in to comment.