X Tutup
Skip to content

Commit 29a24ab

Browse files
committed
fstab-generator: if usr= is specified, mount it to /sysusr/usr/ first
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.
1 parent ee7561d commit 29a24ab

File tree

7 files changed

+100
-17
lines changed

7 files changed

+100
-17
lines changed

src/basic/special.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#define SPECIAL_INITRD_FS_TARGET "initrd-fs.target"
3838
#define SPECIAL_INITRD_ROOT_DEVICE_TARGET "initrd-root-device.target"
3939
#define SPECIAL_INITRD_ROOT_FS_TARGET "initrd-root-fs.target"
40+
#define SPECIAL_INITRD_USR_FS_TARGET "initrd-usr-fs.target"
4041
#define SPECIAL_REMOTE_FS_TARGET "remote-fs.target" /* LSB's $remote_fs */
4142
#define SPECIAL_REMOTE_FS_PRE_TARGET "remote-fs-pre.target"
4243
#define SPECIAL_SWAP_TARGET "swap.target"

src/fstab-generator/fstab-generator.c

Lines changed: 77 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -744,6 +744,10 @@ static int add_sysroot_mount(void) {
744744
static int add_sysroot_usr_mount(void) {
745745
_cleanup_free_ char *what = NULL;
746746
const char *opts;
747+
int r;
748+
749+
/* Returns 0 if we didn't do anything, > 0 if we either generated a unit for the /usr/ mount, or we
750+
* know for sure something else did */
747751

748752
if (!arg_usr_what && !arg_usr_fstype && !arg_usr_options)
749753
return 0;
@@ -767,8 +771,23 @@ static int add_sysroot_usr_mount(void) {
767771
return log_oom();
768772
}
769773

770-
if (!arg_usr_what)
774+
if (isempty(arg_usr_what)) {
775+
log_debug("Could not find a usr= entry on the kernel command line.");
771776
return 0;
777+
}
778+
779+
if (streq(arg_usr_what, "gpt-auto")) {
780+
/* This is handled by the gpt-auto generator */
781+
log_debug("Skipping /usr/ directory handling, as gpt-auto was requested.");
782+
return 1; /* systemd-gpt-auto-generator will generate a unit for this, hence report that a
783+
* unit file is being created for the host /usr/ mount. */
784+
}
785+
786+
if (path_equal(arg_usr_what, "/dev/nfs")) {
787+
/* This is handled by the initrd (if at all supported, that is) */
788+
log_debug("Skipping /usr/ directory handling, as /dev/nfs was requested.");
789+
return 1; /* As above, report that NFS code will create the unit */
790+
}
772791

773792
what = fstab_node_to_udev_node(arg_usr_what);
774793
if (!what)
@@ -781,17 +800,62 @@ static int add_sysroot_usr_mount(void) {
781800
else
782801
opts = arg_usr_options;
783802

784-
log_debug("Found entry what=%s where=/sysroot/usr type=%s", what, strna(arg_usr_fstype));
785-
return add_mount(arg_dest,
786-
what,
787-
"/sysroot/usr",
788-
NULL,
789-
arg_usr_fstype,
790-
opts,
791-
is_device_path(what) ? 1 : 0, /* passno */
792-
0,
793-
SPECIAL_INITRD_FS_TARGET,
794-
"/proc/cmdline");
803+
/* When mounting /usr from the initrd, we add an extra level of indirection: we first mount the /usr/
804+
* partition to /sysusr/usr/, and then afterwards bind mount that to /sysroot/usr/. We do this so
805+
* that we can cover for systems that initially only have a /usr/ around and where the root fs needs
806+
* to be synthesized, based on configuration included in /usr/, e.g. systemd-repart. Software like
807+
* this should order itself after initrd-usr-fs.target and before initrd-fs.target; and it should
808+
* look into both /sysusr/ and /sysroot/ for the configuration data to apply. */
809+
810+
log_debug("Found entry what=%s where=/sysusr/usr type=%s opts=%s", what, strna(arg_usr_fstype), strempty(opts));
811+
812+
r = add_mount(arg_dest,
813+
what,
814+
"/sysusr/usr",
815+
NULL,
816+
arg_usr_fstype,
817+
opts,
818+
is_device_path(what) ? 1 : 0, /* passno */
819+
0,
820+
SPECIAL_INITRD_USR_FS_TARGET,
821+
"/proc/cmdline");
822+
if (r < 0)
823+
return r;
824+
825+
log_debug("Synthesizing entry what=/sysusr/usr where=/sysrootr/usr opts=bind");
826+
827+
r = add_mount(arg_dest,
828+
"/sysusr/usr",
829+
"/sysroot/usr",
830+
NULL,
831+
NULL,
832+
"bind",
833+
0,
834+
0,
835+
SPECIAL_INITRD_FS_TARGET,
836+
"/proc/cmdline");
837+
if (r < 0)
838+
return r;
839+
840+
return 1;
841+
}
842+
843+
static int add_sysroot_usr_mount_or_fallback(void) {
844+
int r;
845+
846+
r = add_sysroot_usr_mount();
847+
if (r != 0)
848+
return r;
849+
850+
/* OK, so we didn't write anything out for /sysusr/usr/ nor /sysroot/usr/. In this case, let's make
851+
* sure that initrd-usr-fs.target is at least ordered after sysroot.mount so that services that order
852+
* themselves get the guarantee that /usr/ is definitely mounted somewhere. */
853+
854+
return generator_add_symlink(
855+
arg_dest,
856+
SPECIAL_INITRD_USR_FS_TARGET,
857+
"requires",
858+
"sysroot.mount");
795859
}
796860

797861
static int add_volatile_root(void) {
@@ -953,7 +1017,7 @@ static int run(const char *dest, const char *dest_early, const char *dest_late)
9531017
if (in_initrd()) {
9541018
r = add_sysroot_mount();
9551019

956-
r2 = add_sysroot_usr_mount();
1020+
r2 = add_sysroot_usr_mount_or_fallback();
9571021

9581022
r3 = add_volatile_root();
9591023
} else

units/initrd-usr-fs.target

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# SPDX-License-Identifier: LGPL-2.1-or-later
2+
#
3+
# This file is part of systemd.
4+
#
5+
# systemd is free software; you can redistribute it and/or modify it
6+
# under the terms of the GNU Lesser General Public License as published by
7+
# the Free Software Foundation; either version 2.1 of the License, or
8+
# (at your option) any later version.
9+
10+
[Unit]
11+
Description=Initrd /usr File System
12+
Documentation=man:systemd.special(7)
13+
AssertPathExists=/etc/initrd-release
14+
OnFailure=emergency.target
15+
OnFailureJobMode=replace-irreversibly
16+
DefaultDependencies=no
17+
Conflicts=shutdown.target

units/initrd.target

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,6 @@ OnFailure=emergency.target
1414
OnFailureJobMode=replace-irreversibly
1515
AssertPathExists=/etc/initrd-release
1616
Requires=basic.target
17-
Wants=initrd-root-fs.target initrd-root-device.target initrd-fs.target initrd-parse-etc.service
18-
After=initrd-root-fs.target initrd-root-device.target initrd-fs.target basic.target rescue.service rescue.target
17+
Wants=initrd-root-fs.target initrd-root-device.target initrd-fs.target initrd-usr-fs.target initrd-parse-etc.service
18+
After=initrd-root-fs.target initrd-root-device.target initrd-fs.target initrd-usr-fs.target basic.target rescue.service rescue.target
1919
AllowIsolate=yes

units/meson.build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ units = [
3838
['initrd-switch-root.service', 'ENABLE_INITRD'],
3939
['initrd-switch-root.target', 'ENABLE_INITRD'],
4040
['initrd-udevadm-cleanup-db.service', 'ENABLE_INITRD'],
41+
['initrd-usr-fs.target', 'ENABLE_INITRD'],
4142
['initrd.target', 'ENABLE_INITRD'],
4243
['kexec.target', ''],
4344
['ldconfig.service', 'ENABLE_LDCONFIG',

units/systemd-repart.service.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ Description=Repartition Root Disk
1212
Documentation=man:systemd-repart.service(8)
1313
DefaultDependencies=no
1414
Conflicts=shutdown.target
15-
After=sysroot.mount
15+
After=initrd-usr-fs.target
1616
Before=initrd-root-fs.target shutdown.target
1717
ConditionVirtualization=!container
1818
ConditionDirectoryNotEmpty=|/usr/lib/repart.d

units/systemd-volatile-root.service.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ Description=Enforce Volatile Root File Systems
1212
Documentation=man:systemd-volatile-root.service(8)
1313
DefaultDependencies=no
1414
Conflicts=shutdown.target
15-
After=sysroot.mount systemd-repart.service
15+
After=sysroot.mount sysroot-usr.mount systemd-repart.service
1616
Before=initrd-root-fs.target shutdown.target
1717
AssertPathExists=/etc/initrd-release
1818

0 commit comments

Comments
 (0)
X Tutup