#include "virt.h"
#include "volatile-util.h"
-typedef enum MountpointFlags {
- NOAUTO = 1 << 0,
- NOFAIL = 1 << 1,
- AUTOMOUNT = 1 << 2,
- MAKEFS = 1 << 3,
- GROWFS = 1 << 4,
- RWONLY = 1 << 5,
-} MountpointFlags;
+typedef enum MountPointFlags {
+ MOUNT_NOAUTO = 1 << 0,
+ MOUNT_NOFAIL = 1 << 1,
+ MOUNT_AUTOMOUNT = 1 << 2,
+ MOUNT_MAKEFS = 1 << 3,
+ MOUNT_GROWFS = 1 << 4,
+ MOUNT_RW_ONLY = 1 << 5,
+} MountPointFlags;
static const char *arg_dest = NULL;
static const char *arg_dest_late = NULL;
static int add_swap(
const char *what,
struct mntent *me,
- MountpointFlags flags) {
+ MountPointFlags flags) {
_cleanup_free_ char *name = NULL;
_cleanup_fclose_ FILE *f = NULL;
if (r < 0)
return r;
- if (flags & MAKEFS) {
+ if (flags & MOUNT_MAKEFS) {
r = generator_hook_up_mkswap(arg_dest, what);
if (r < 0)
return r;
}
- if (flags & GROWFS)
+ if (flags & MOUNT_GROWFS)
/* TODO: swap devices must be wiped and recreated */
log_warning("%s: growing swap devices is currently unsupported.", what);
- if (!(flags & NOAUTO)) {
+ if (!(flags & MOUNT_NOAUTO)) {
r = generator_add_symlink(arg_dest, SPECIAL_SWAP_TARGET,
- (flags & NOFAIL) ? "wants" : "requires", name);
+ (flags & MOUNT_NOFAIL) ? "wants" : "requires", name);
if (r < 0)
return r;
}
const char *fstype,
const char *opts,
int passno,
- MountpointFlags flags,
+ MountPointFlags flags,
const char *post,
const char *source) {
return r;
if (path_equal(where, "/")) {
- if (flags & NOAUTO)
- log_warning("Ignoring \"noauto\" for root device");
- if (flags & NOFAIL)
- log_warning("Ignoring \"nofail\" for root device");
- if (flags & AUTOMOUNT)
- log_warning("Ignoring automount option for root device");
+ if (flags & MOUNT_NOAUTO)
+ log_warning("Ignoring \"noauto\" option for root device");
+ if (flags & MOUNT_NOFAIL)
+ log_warning("Ignoring \"nofail\" option for root device");
+ if (flags & MOUNT_AUTOMOUNT)
+ log_warning("Ignoring \"automount\" option for root device");
if (!strv_isempty(wanted_by))
- log_warning("Ignoring \"x-systemd.wanted-by=\" for root device");
+ log_warning("Ignoring \"x-systemd.wanted-by=\" option for root device");
if (!strv_isempty(required_by))
- log_warning("Ignoring \"x-systemd.required-by=\" for root device");
+ log_warning("Ignoring \"x-systemd.required-by=\" option for root device");
required_by = strv_free(required_by);
wanted_by = strv_free(wanted_by);
- SET_FLAG(flags, NOAUTO | NOFAIL | AUTOMOUNT, false);
+ SET_FLAG(flags, MOUNT_NOAUTO | MOUNT_NOFAIL | MOUNT_AUTOMOUNT, false);
}
r = unit_name_from_path(where, ".mount", &name);
"SourcePath=%s\n",
source);
- if (STRPTR_IN_SET(fstype, "nfs", "nfs4") && !(flags & AUTOMOUNT) &&
+ if (STRPTR_IN_SET(fstype, "nfs", "nfs4") && !(flags & MOUNT_AUTOMOUNT) &&
fstab_test_yes_no_option(opts, "bg\0" "fg\0")) {
/* The default retry timeout that mount.nfs uses for 'bg' mounts
* is 10000 minutes, where as it uses 2 minutes for 'fg' mounts.
* By placing these options first, they can be overridden by
* settings in /etc/fstab. */
opts = strjoina("x-systemd.mount-timeout=infinity,retry=10000,nofail,", opts, ",fg");
- SET_FLAG(flags, NOFAIL, true);
+ SET_FLAG(flags, MOUNT_NOFAIL, true);
}
r = write_extra_dependencies(f, opts);
if (r < 0)
return r;
+ /* Order the mount unit we generate relative to the post unit, so that DefaultDependencies= on the
+ * target unit won't affect us. */
+ if (post && !FLAGS_SET(flags, MOUNT_AUTOMOUNT) && !FLAGS_SET(flags, MOUNT_NOAUTO))
+ fprintf(f, "Before=%s\n", post);
+
if (passno != 0) {
r = generator_write_fsck_deps(f, dest, what, where, fstype);
if (r < 0)
if (r < 0)
return r;
- if (flags & RWONLY)
+ if (flags & MOUNT_RW_ONLY)
fprintf(f, "ReadWriteOnly=yes\n");
r = fflush_and_check(f);
if (r < 0)
return log_error_errno(r, "Failed to write unit file %s: %m", name);
- if (flags & MAKEFS) {
+ if (flags & MOUNT_MAKEFS) {
r = generator_hook_up_mkfs(dest, what, where, fstype);
if (r < 0)
return r;
}
- if (flags & GROWFS) {
+ if (flags & MOUNT_GROWFS) {
r = generator_hook_up_growfs(dest, where, post);
if (r < 0)
return r;
}
- if (!FLAGS_SET(flags, AUTOMOUNT)) {
- if (!FLAGS_SET(flags, NOAUTO) && strv_isempty(wanted_by) && strv_isempty(required_by)) {
+ if (!FLAGS_SET(flags, MOUNT_AUTOMOUNT)) {
+ if (!FLAGS_SET(flags, MOUNT_NOAUTO) && strv_isempty(wanted_by) && strv_isempty(required_by)) {
r = generator_add_symlink(dest, post,
- (flags & NOFAIL) ? "wants" : "requires", name);
+ (flags & MOUNT_NOFAIL) ? "wants" : "requires", name);
if (r < 0)
return r;
} else {
return log_error_errno(r, "Failed to write unit file %s: %m", automount_name);
r = generator_add_symlink(dest, post,
- (flags & NOFAIL) ? "wants" : "requires", automount_name);
+ (flags & MOUNT_NOFAIL) ? "wants" : "requires", automount_name);
if (r < 0)
return r;
}
while ((me = getmntent(f))) {
_cleanup_free_ char *where = NULL, *what = NULL, *canonical_where = NULL;
- bool makefs, growfs, noauto, nofail, rwonly;
+ bool makefs, growfs, noauto, nofail;
+ MountPointFlags flags;
int k;
if (initrd && !mount_in_initrd(me))
return log_oom();
if (is_path(where)) {
- path_simplify(where, false);
+ path_simplify(where);
/* Follow symlinks here; see 5261ba901845c084de5a8fd06500ed09bfb0bd80 which makes sense for
* mount units, but causes problems since it historically worked to have symlinks in e.g.
makefs = fstab_test_option(me->mnt_opts, "x-systemd.makefs\0");
growfs = fstab_test_option(me->mnt_opts, "x-systemd.growfs\0");
- rwonly = fstab_test_option(me->mnt_opts, "x-systemd.rw-only\0");
noauto = fstab_test_yes_no_option(me->mnt_opts, "noauto\0" "auto\0");
nofail = fstab_test_yes_no_option(me->mnt_opts, "nofail\0" "fail\0");
yes_no(makefs), yes_no(growfs),
yes_no(noauto), yes_no(nofail));
+ flags = makefs * MOUNT_MAKEFS |
+ growfs * MOUNT_GROWFS |
+ noauto * MOUNT_NOAUTO |
+ nofail * MOUNT_NOFAIL;
+
if (streq(me->mnt_type, "swap"))
- k = add_swap(what, me,
- makefs*MAKEFS | growfs*GROWFS | noauto*NOAUTO | nofail*NOFAIL);
+ k = add_swap(what, me, flags);
else {
- bool automount;
+ bool rw_only, automount;
const char *post;
+ rw_only = fstab_test_option(me->mnt_opts, "x-systemd.rw-only\0");
automount = fstab_test_option(me->mnt_opts,
"comment=systemd.automount\0"
"x-systemd.automount\0");
+
+ flags |= rw_only * MOUNT_RW_ONLY |
+ automount * MOUNT_AUTOMOUNT;
+
if (initrd)
post = SPECIAL_INITRD_FS_TARGET;
else if (mount_is_network(me))
me->mnt_type,
me->mnt_opts,
me->mnt_passno,
- makefs*MAKEFS | growfs*GROWFS | noauto*NOAUTO | nofail*NOFAIL | automount*AUTOMOUNT | rwonly*RWONLY,
+ flags,
post,
fstab);
}
else
opts = arg_root_options;
- log_debug("Found entry what=%s where=/sysroot type=%s", what, strna(arg_root_fstype));
+ log_debug("Found entry what=%s where=/sysroot type=%s opts=%s", what, strna(arg_root_fstype), strempty(opts));
if (is_device_path(what)) {
r = generator_write_initrd_root_device_deps(arg_dest, what);
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;
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)
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) {
return 0;
return generator_add_symlink(arg_dest, SPECIAL_INITRD_ROOT_FS_TARGET, "requires",
- SYSTEM_DATA_UNIT_PATH "/" SPECIAL_VOLATILE_ROOT_SERVICE);
+ SYSTEM_DATA_UNIT_DIR "/" SPECIAL_VOLATILE_ROOT_SERVICE);
}
static int add_volatile_var(void) {
if (in_initrd()) {
r = add_sysroot_mount();
- r2 = add_sysroot_usr_mount();
+ r2 = add_sysroot_usr_mount_or_fallback();
r3 = add_volatile_root();
} else