diff --git a/TODO b/TODO
index 462db57a3a..b4e0cbb88a 100644
--- a/TODO
+++ b/TODO
@@ -825,6 +825,7 @@ Features:
- man: document the very specific env the shutdown drop-in tools live in
- man: add more examples to man pages
- man: maybe sort directives in man pages, and take sections from --help and apply them to man too
+ - document root=gpt-auto properly
* systemctl:
- add systemctl switch to dump transaction without executing it
diff --git a/man/kernel-command-line.xml b/man/kernel-command-line.xml
index 43dfc1073b..e39f108d8f 100644
--- a/man/kernel-command-line.xml
+++ b/man/kernel-command-line.xml
@@ -329,7 +329,7 @@
Configures the root file system and its file system
type and mount options, as well as whether it shall be
- mounted read-only or read-writable initially. For details,
+ mounted read-only or read-write initially. For details,
see
systemd-fstab-generator8.
diff --git a/man/systemd-gpt-auto-generator.xml b/man/systemd-gpt-auto-generator.xml
index d98ef2003f..5ae4343705 100644
--- a/man/systemd-gpt-auto-generator.xml
+++ b/man/systemd-gpt-auto-generator.xml
@@ -196,6 +196,45 @@
systemd.generator7.
+
+ Kernel Command Line
+
+ systemd-gpt-auto-generator understands the following kernel command line
+ parameters:
+
+
+
+
+ systemd.gpt_auto
+ rd.systemd.gpt_auto
+
+ Those options take an optional boolean argument, and default to yes.
+ The generator is enabled by default, and a negative value may be used to disable it.
+
+
+
+
+ root=
+
+ When used with the special value gpt-auto, automatic discovery of
+ the root parition based on the GPT partition type is enabled. Any other value disables this
+ generator.
+
+
+
+ rw
+ ro
+
+ Mount the root partition read-write or read-only initially.
+
+ Note that unlike most kernel command line options these settings do not override configuration
+ in the file system, and the file system may be remounted later. See
+ systemd-remount-fs.service8.
+
+
+
+
+
See Also
diff --git a/man/systemd-remount-fs.service.xml b/man/systemd-remount-fs.service.xml
index 988a617406..46ab56eb0b 100644
--- a/man/systemd-remount-fs.service.xml
+++ b/man/systemd-remount-fs.service.xml
@@ -30,26 +30,31 @@
Description
- systemd-remount-fs.service is an
- early boot service that applies mount options listed in
- fstab5
- to the root file system, the /usr file system,
- and the kernel API file systems. This is required so that the
- mount options of these file systems — which are pre-mounted by
- the kernel, the initial RAM disk, container environments or system
- manager code — are updated to those listed in
- /etc/fstab. This service ignores normal file
- systems and only changes the root file system (i.e.
- /), /usr and the virtual
- kernel API file systems such as /proc,
- /sys or /dev. This
- service executes no operation if /etc/fstab
- does not exist or lists no entries for the mentioned file
- systems.
+ systemd-remount-fs.service is an early boot service that applies mount options
+ listed in fstab5, or
+ gathered from the partition table (when
+ systemd-gpt-auto-generator8
+ is active) to the root file system, the /usr file system, and the kernel API file
+ systems. This is required so that the mount options of these file systems — which are pre-mounted by the
+ kernel, the initial RAM disk, container environments or system manager code — are updated to those
+ configured in /etc/fstab and the other sources. This service ignores normal file
+ systems and only changes the root file system (i.e. /), /usr,
+ and the virtual kernel API file systems such as /proc, /sys or
+ /dev. This service executes no operation if no configuration is found
+ (/etc/fstab does not exist or lists no entries for the mentioned file systems, or
+ the partition table does not contain relevant entries).
For a longer discussion of kernel API file systems see
API
File Systems.
+
+ Note: systemd-remount-fs.service is usually pulled in by
+ systemd-fstab-generator8,
+ hence it is also affected by the kernel command line option fstab=, which may be used
+ to disable the generator. It may also pulled in by
+ systemd-gpt-auto-generator8,
+ which is affected by systemd.gpt_auto and other options.
@@ -57,7 +62,9 @@
systemd1,
fstab5,
- mount8
+ mount8,
+ systemd-fstab-generator8,
+ systemd-gpt-auto-generator8
diff --git a/src/basic/special.h b/src/basic/special.h
index 379a3d7979..add1c1d507 100644
--- a/src/basic/special.h
+++ b/src/basic/special.h
@@ -76,9 +76,11 @@
/* Magic early boot services */
#define SPECIAL_FSCK_SERVICE "systemd-fsck@.service"
+#define SPECIAL_FSCK_ROOT_SERVICE "systemd-fsck-root.service"
#define SPECIAL_QUOTACHECK_SERVICE "systemd-quotacheck.service"
#define SPECIAL_QUOTAON_SERVICE "quotaon.service"
#define SPECIAL_REMOUNT_FS_SERVICE "systemd-remount-fs.service"
+#define SPECIAL_VOLATILE_ROOT_SERVICE "systemd-volatile-root.service"
/* Services systemd relies on */
#define SPECIAL_DBUS_SERVICE "dbus.service"
diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c
index f3c223a270..30a6d356d0 100644
--- a/src/fstab-generator/fstab-generator.c
+++ b/src/fstab-generator/fstab-generator.c
@@ -518,6 +518,8 @@ static int parse_fstab(bool initrd) {
int r = 0;
fstab_path = initrd ? "/sysroot/etc/fstab" : "/etc/fstab";
+ log_debug("Parsing %s...", fstab_path);
+
f = setmntent(fstab_path, "re");
if (!f) {
if (errno == ENOENT)
@@ -720,23 +722,14 @@ static int add_sysroot_usr_mount(void) {
}
static int add_volatile_root(void) {
- const char *from, *to;
+ /* Let's add in systemd-remount-volatile.service which will remount the root device to tmpfs if this is
+ * requested, leaving only /usr from the root mount inside. */
if (arg_volatile_mode != VOLATILE_YES)
return 0;
- /* Let's add in systemd-remount-volatile.service which will remount the root device to tmpfs if this is
- * requested, leaving only /usr from the root mount inside. */
-
- from = strjoina(SYSTEM_DATA_UNIT_PATH "/systemd-volatile-root.service");
- to = strjoina(arg_dest, "/" SPECIAL_INITRD_ROOT_FS_TARGET, ".requires/systemd-volatile-root.service");
-
- (void) mkdir_parents(to, 0755);
-
- if (symlink(from, to) < 0)
- return log_error_errno(errno, "Failed to hook in volatile remount service: %m");
-
- return 0;
+ return generator_add_symlink(arg_dest, SPECIAL_INITRD_ROOT_FS_TARGET, "requires",
+ SYSTEM_DATA_UNIT_PATH "/" SPECIAL_VOLATILE_ROOT_SERVICE);
}
static int add_volatile_var(void) {
@@ -868,7 +861,7 @@ static int determine_root(void) {
}
static int run(const char *dest, const char *dest_early, const char *dest_late) {
- int r;
+ int r, r2 = 0, r3 = 0;
assert_se(arg_dest = dest);
assert_se(arg_dest_late = dest_late);
@@ -881,42 +874,27 @@ static int run(const char *dest, const char *dest_early, const char *dest_late)
/* Always honour root= and usr= in the kernel command line if we are in an initrd */
if (in_initrd()) {
- int k;
-
r = add_sysroot_mount();
- k = add_sysroot_usr_mount();
- if (k < 0)
- r = k;
+ r2 = add_sysroot_usr_mount();
- k = add_volatile_root();
- if (k < 0)
- r = k;
+ r3 = add_volatile_root();
} else
r = add_volatile_var();
/* Honour /etc/fstab only when that's enabled */
if (arg_fstab_enabled) {
- int k;
-
- log_debug("Parsing /etc/fstab");
-
/* Parse the local /etc/fstab, possibly from the initrd */
- k = parse_fstab(false);
- if (k < 0)
- r = k;
+ r2 = parse_fstab(false);
/* If running in the initrd also parse the /etc/fstab from the host */
- if (in_initrd()) {
- log_debug("Parsing /sysroot/etc/fstab");
-
- k = parse_fstab(true);
- if (k < 0)
- r = k;
- }
+ if (in_initrd())
+ r3 = parse_fstab(true);
+ else
+ r3 = generator_enable_remount_fs_service(arg_dest);
}
- return r;
+ return r < 0 ? r : r2 < 0 ? r2 : r3;
}
DEFINE_MAIN_GENERATOR_FUNCTION(run);
diff --git a/src/gpt-auto-generator/gpt-auto-generator.c b/src/gpt-auto-generator/gpt-auto-generator.c
index d9e29c47f3..09c0bcba2d 100644
--- a/src/gpt-auto-generator/gpt-auto-generator.c
+++ b/src/gpt-auto-generator/gpt-auto-generator.c
@@ -467,13 +467,13 @@ static int add_root_rw(DissectedPartition *p) {
return 0;
}
+ (void) generator_enable_remount_fs_service(arg_dest);
+
path = strjoina(arg_dest, "/systemd-remount-fs.service.d/50-remount-rw.conf");
(void) mkdir_parents(path, 0755);
r = write_string_file(path,
"# Automatically generated by systemd-gpt-generator\n\n"
- "[Unit]\n"
- "ConditionPathExists=\n\n" /* We need to turn off the ConditionPathExist= in the main unit file */
"[Service]\n"
"Environment=SYSTEMD_REMOUNT_ROOT_RW=1\n",
WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_NOFOLLOW);
@@ -678,6 +678,9 @@ static int add_root_mount(void) {
return r;
}
+ /* Note that we do not need to enable systemd-remount-fs.service here. If
+ * /etc/fstab exists, systemd-fstab-generator will pull it in for us. */
+
return add_mount(
"root",
"/dev/gpt-auto-root",
diff --git a/src/remount-fs/remount-fs.c b/src/remount-fs/remount-fs.c
index 0bac355e0f..0df29aa69f 100644
--- a/src/remount-fs/remount-fs.c
+++ b/src/remount-fs/remount-fs.c
@@ -47,6 +47,31 @@ static int track_pid(Hashmap **h, const char *path, pid_t pid) {
return 0;
}
+static int do_remount(const char *path, bool force_rw, Hashmap **pids) {
+ pid_t pid;
+ int r;
+
+ log_debug("Remounting %s...", path);
+
+ r = safe_fork(force_rw ? "(remount-rw)" : "(remount)",
+ FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
+ if (r < 0)
+ return r;
+ if (r == 0) {
+ /* Child */
+ execv(MOUNT_PATH,
+ STRV_MAKE(MOUNT_PATH,
+ path,
+ "-o",
+ force_rw ? "remount,rw" : "remount"));
+ log_error_errno(errno, "Failed to execute " MOUNT_PATH ": %m");
+ _exit(EXIT_FAILURE);
+ }
+
+ /* Parent */
+ return track_pid(pids, path, pid);
+}
+
static int run(int argc, char *argv[]) {
_cleanup_hashmap_free_free_ Hashmap *pids = NULL;
_cleanup_endmntent_ FILE *f = NULL;
@@ -66,36 +91,20 @@ static int run(int argc, char *argv[]) {
if (!f) {
if (errno != ENOENT)
return log_error_errno(errno, "Failed to open /etc/fstab: %m");
- } else {
+ } else
while ((me = getmntent(f))) {
- pid_t pid;
-
- /* Remount the root fs, /usr and all API VFS */
+ /* Remount the root fs, /usr, and all API VFSs */
if (!mount_point_is_api(me->mnt_dir) &&
!PATH_IN_SET(me->mnt_dir, "/", "/usr"))
continue;
- log_debug("Remounting %s...", me->mnt_dir);
-
if (path_equal(me->mnt_dir, "/"))
has_root = true;
- r = safe_fork("(remount)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
- if (r < 0)
- return r;
- if (r == 0) {
- /* Child */
- execv(MOUNT_PATH, STRV_MAKE(MOUNT_PATH, me->mnt_dir, "-o", "remount"));
- log_error_errno(errno, "Failed to execute " MOUNT_PATH ": %m");
- _exit(EXIT_FAILURE);
- }
-
- /* Parent */
- r = track_pid(&pids, me->mnt_dir, pid);
+ r = do_remount(me->mnt_dir, false, &pids);
if (r < 0)
return r;
}
- }
if (!has_root) {
/* The $SYSTEMD_REMOUNT_ROOT_RW environment variable is set by systemd-gpt-auto-generator to tell us
@@ -103,27 +112,14 @@ static int run(int argc, char *argv[]) {
* which takes precedence. */
r = getenv_bool("SYSTEMD_REMOUNT_ROOT_RW");
- if (r > 0) {
- pid_t pid;
-
- log_debug("Remounting / writable...");
-
- r = safe_fork("(remount-rw)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &pid);
- if (r < 0)
- return r;
- if (r == 0) {
- /* Child */
- execv(MOUNT_PATH, STRV_MAKE(MOUNT_PATH, "/", "-o", "remount,rw"));
- log_error_errno(errno, "Failed to execute " MOUNT_PATH ": %m");
- _exit(EXIT_FAILURE);
- }
-
- r = track_pid(&pids, "/", pid);
- if (r < 0)
- return r;
-
- } else if (r < 0 && r != -ENXIO)
+ if (r < 0 && r != -ENXIO)
log_warning_errno(r, "Failed to parse $SYSTEMD_REMOUNT_ROOT_RW, ignoring: %m");
+
+ if (r > 0) {
+ r = do_remount("/", true, &pids);
+ if (r < 0)
+ return r;
+ }
}
r = 0;
diff --git a/src/shared/generator.c b/src/shared/generator.c
index 0adaaf2c56..b2085040f0 100644
--- a/src/shared/generator.c
+++ b/src/shared/generator.c
@@ -55,13 +55,14 @@ int generator_open_unit_file(
return 0;
}
-int generator_add_symlink(const char *root, const char *dst, const char *dep_type, const char *src) {
- /* Adds a symlink from ..d/ to ../ */
+int generator_add_symlink(const char *dir, const char *dst, const char *dep_type, const char *src) {
+ /* Adds a symlink from ./ to (if src is absolute)
+ * or ../ (otherwise). */
const char *from, *to;
- from = strjoina("../", src);
- to = strjoina(root, "/", dst, ".", dep_type, "/", src);
+ from = path_is_absolute(src) ? src : strjoina("../", src);
+ to = strjoina(dir, "/", dst, ".", dep_type, "/", basename(src));
mkdir_parents_label(to, 0755);
if (symlink(from, to) < 0)
@@ -85,7 +86,7 @@ static int write_fsck_sysroot_service(const char *dir, const char *what) {
if (!escaped2)
return log_oom();
- unit = strjoina(dir, "/systemd-fsck-root.service");
+ unit = strjoina(dir, "/"SPECIAL_FSCK_ROOT_SERVICE);
log_debug("Creating %s", unit);
r = unit_name_from_path(what, ".device", &device);
@@ -157,10 +158,10 @@ int generator_write_fsck_deps(
if (path_equal(where, "/")) {
const char *lnk;
- lnk = strjoina(dir, "/" SPECIAL_LOCAL_FS_TARGET ".wants/systemd-fsck-root.service");
+ lnk = strjoina(dir, "/" SPECIAL_LOCAL_FS_TARGET ".wants/"SPECIAL_FSCK_ROOT_SERVICE);
mkdir_parents(lnk, 0755);
- if (symlink(SYSTEM_DATA_UNIT_PATH "/systemd-fsck-root.service", lnk) < 0)
+ if (symlink(SYSTEM_DATA_UNIT_PATH "/"SPECIAL_FSCK_ROOT_SERVICE, lnk) < 0)
return log_error_errno(errno, "Failed to create symlink %s: %m", lnk);
} else {
@@ -172,7 +173,7 @@ int generator_write_fsck_deps(
if (r < 0)
return r;
- fsck = "systemd-fsck-root.service";
+ fsck = SPECIAL_FSCK_ROOT_SERVICE;
} else {
r = unit_name_from_path_instance("systemd-fsck", what, ".service", &_fsck);
if (r < 0)
@@ -498,6 +499,12 @@ int generator_hook_up_growfs(
return generator_add_symlink(dir, where_unit, "wants", unit);
}
+int generator_enable_remount_fs_service(const char *dir) {
+ /* Pull in systemd-remount-fs.service */
+ return generator_add_symlink(dir, SPECIAL_LOCAL_FS_TARGET, "wants",
+ SYSTEM_DATA_UNIT_PATH "/" SPECIAL_REMOUNT_FS_SERVICE);
+}
+
void log_setup_generator(void) {
log_set_prohibit_ipc(true);
log_setup_service();
diff --git a/src/shared/generator.h b/src/shared/generator.h
index 5a1c1e32f7..fa002a9114 100644
--- a/src/shared/generator.h
+++ b/src/shared/generator.h
@@ -11,7 +11,7 @@ int generator_open_unit_file(
const char *name,
FILE **file);
-int generator_add_symlink(const char *root, const char *dst, const char *dep_type, const char *src);
+int generator_add_symlink(const char *dir, const char *dst, const char *dep_type, const char *src);
int generator_write_fsck_deps(
FILE *f,
@@ -50,6 +50,8 @@ int generator_hook_up_growfs(
const char *where,
const char *target);
+int generator_enable_remount_fs_service(const char *dir);
+
void log_setup_generator(void);
/* Similar to DEFINE_MAIN_FUNCTION, but initializes logging and assigns positional arguments. */
diff --git a/src/test/test-unit-name.c b/src/test/test-unit-name.c
index 0d3674cff8..959d6d4614 100644
--- a/src/test/test-unit-name.c
+++ b/src/test/test-unit-name.c
@@ -759,7 +759,7 @@ static void test_unit_name_from_dbus_path(void) {
test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dcoredump_2esocket", 0, "systemd-coredump.socket");
test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dcoredump_400_2eservice", 0, "systemd-coredump@0.service");
test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dfirstboot_2eservice", 0, "systemd-firstboot.service");
- test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dfsck_2droot_2eservice", 0, "systemd-fsck-root.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dfsck_2droot_2eservice", 0, SPECIAL_FSCK_ROOT_SERVICE);
test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dhwdb_2dupdate_2eservice", 0, "systemd-hwdb-update.service");
test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dinitctl_2eservice", 0, "systemd-initctl.service");
test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dinitctl_2esocket", 0, "systemd-initctl.socket");
diff --git a/units/meson.build b/units/meson.build
index d69508467f..3820585051 100644
--- a/units/meson.build
+++ b/units/meson.build
@@ -186,8 +186,7 @@ in_units = [
['systemd-quotacheck.service', 'ENABLE_QUOTACHECK'],
['systemd-random-seed.service', 'ENABLE_RANDOMSEED',
'sysinit.target.wants/'],
- ['systemd-remount-fs.service', '',
- 'local-fs.target.wants/'],
+ ['systemd-remount-fs.service', ''],
['systemd-resolved.service', 'ENABLE_RESOLVE',
join_paths(pkgsysconfdir, 'system/dbus-org.freedesktop.resolve1.service') + ' ' +
join_paths(pkgsysconfdir, 'system/multi-user.target.wants/')],
diff --git a/units/systemd-remount-fs.service.in b/units/systemd-remount-fs.service.in
index 2e5b75ec03..4f4304d68e 100644
--- a/units/systemd-remount-fs.service.in
+++ b/units/systemd-remount-fs.service.in
@@ -16,7 +16,6 @@ Conflicts=shutdown.target
After=systemd-fsck-root.service
Before=local-fs-pre.target local-fs.target shutdown.target
Wants=local-fs-pre.target
-ConditionPathExists=/etc/fstab
[Service]
Type=oneshot