diff --git a/Makefile.am b/Makefile.am
index aea91e9c94..c126f65ad2 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -467,6 +467,7 @@ dist_systemunit_DATA = \
units/local-fs-pre.target \
units/initrd.target \
units/initrd-fs.target \
+ units/initrd-root-device.target \
units/initrd-root-fs.target \
units/remote-fs.target \
units/remote-fs-pre.target \
diff --git a/man/bootup.xml b/man/bootup.xml
index b92057af29..986996398c 100644
--- a/man/bootup.xml
+++ b/man/bootup.xml
@@ -179,6 +179,8 @@
identical to the system manager bootup (see above) until it
reaches basic.target. From there, systemd
approaches the special target initrd.target.
+ When the root device becomes available,
+ initd-root-device.target is reached.
If the root device can be mounted at
/sysroot, the
sysroot.mount unit becomes active and
@@ -204,7 +206,10 @@
| emergency.service
______________________/| |
/ | v
- | sysroot.mount emergency.target
+ | initrd-root-device.target emergency.target
+ | |
+ | v
+ | sysroot.mount
| |
| v
| initrd-root-fs.target
diff --git a/man/systemd.special.xml b/man/systemd.special.xml
index 14998b9647..26974ed73f 100644
--- a/man/systemd.special.xml
+++ b/man/systemd.special.xml
@@ -83,6 +83,7 @@
remote-fs.target,
remote-fs-pre.target,
rescue.target,
+ initrd-root-device.target,
initrd-root-fs.target,
rpcbind.target,
runlevel2.target,
@@ -464,6 +465,18 @@
SysV.
+
+ initrd-root-device.target
+
+ A special initrd target unit that is reached when the root filesystem device is available, but before
+ it has been mounted.
+ systemd-fstab-generator3
+ and
+ systemd-gpt-auto-generator3
+ automatically setup the appropiate dependencies to make this happen.
+
+
+
initrd-root-fs.target
diff --git a/src/basic/special.h b/src/basic/special.h
index 2fd03d9f75..084d3dfa23 100644
--- a/src/basic/special.h
+++ b/src/basic/special.h
@@ -52,6 +52,7 @@
#define SPECIAL_LOCAL_FS_TARGET "local-fs.target"
#define SPECIAL_LOCAL_FS_PRE_TARGET "local-fs-pre.target"
#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_REMOTE_FS_TARGET "remote-fs.target" /* LSB's $remote_fs */
#define SPECIAL_REMOTE_FS_PRE_TARGET "remote-fs-pre.target"
diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c
index 343e3b1817..108522873e 100644
--- a/src/fstab-generator/fstab-generator.c
+++ b/src/fstab-generator/fstab-generator.c
@@ -489,6 +489,7 @@ static int parse_fstab(bool initrd) {
static int add_sysroot_mount(void) {
_cleanup_free_ char *what = NULL;
const char *opts;
+ int r;
if (isempty(arg_root_what)) {
log_debug("Could not find a root= entry on the kernel command line.");
@@ -508,6 +509,13 @@ static int add_sysroot_mount(void) {
opts = arg_root_options;
log_debug("Found entry what=%s where=/sysroot type=%s", what, strna(arg_root_fstype));
+
+ if (is_device_path(what)) {
+ r = generator_write_initrd_root_device_deps(arg_dest, what);
+ if (r < 0)
+ return r;
+ }
+
return add_mount(what,
"/sysroot",
arg_root_fstype,
diff --git a/src/gpt-auto-generator/gpt-auto-generator.c b/src/gpt-auto-generator/gpt-auto-generator.c
index af96adec06..a4938a7c3a 100644
--- a/src/gpt-auto-generator/gpt-auto-generator.c
+++ b/src/gpt-auto-generator/gpt-auto-generator.c
@@ -956,6 +956,12 @@ static int add_root_mount(void) {
* wait for a root device to show up. A udev rule will create
* the link for us under the right name. */
+ if (in_initrd()) {
+ r = generator_write_initrd_root_device_deps(arg_dest, "/dev/gpt-auto-root");
+ if (r < 0)
+ return 0;
+ }
+
return add_mount(
"root",
"/dev/gpt-auto-root",
diff --git a/src/shared/generator.c b/src/shared/generator.c
index cd3c35cd55..70afc6a285 100644
--- a/src/shared/generator.c
+++ b/src/shared/generator.c
@@ -65,7 +65,7 @@ static int write_fsck_sysroot_service(const char *dir, const char *what) {
"Description=File System Check on %2$s\n"
"DefaultDependencies=no\n"
"BindsTo=%3$s\n"
- "After=%3$s local-fs-pre.target\n"
+ "After=initrd-root-device.target local-fs-pre.target\n"
"Before=shutdown.target\n"
"\n"
"[Service]\n"
@@ -191,3 +191,17 @@ int generator_write_timeouts(
"[Unit]\nJobTimeoutSec=%s",
program_invocation_short_name, timeout);
}
+
+int generator_write_initrd_root_device_deps(const char *dir, const char *what) {
+ _cleanup_free_ char *unit = NULL;
+ int r;
+
+ r = unit_name_from_path(what, ".device", &unit);
+ if (r < 0)
+ return log_error_errno(r, "Failed to make unit name from path: %m");
+
+ return write_drop_in_format(dir, SPECIAL_INITRD_ROOT_DEVICE_TARGET, 50, "root-device",
+ "# Automatically generated by %s\n\n"
+ "[Unit]\nRequires=%s\nAfter=%s",
+ program_invocation_short_name, unit, unit);
+}
diff --git a/src/shared/generator.h b/src/shared/generator.h
index a734e13970..a6017c1b76 100644
--- a/src/shared/generator.h
+++ b/src/shared/generator.h
@@ -34,3 +34,7 @@ int generator_write_timeouts(
const char *where,
const char *opts,
char **filtered);
+
+int generator_write_initrd_root_device_deps(
+ const char *dir,
+ const char *what);
diff --git a/units/initrd-root-device.target b/units/initrd-root-device.target
new file mode 100644
index 0000000000..9d44d2d303
--- /dev/null
+++ b/units/initrd-root-device.target
@@ -0,0 +1,15 @@
+# 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 Root Device
+Documentation=man:systemd.special(7)
+ConditionPathExists=/etc/initrd-release
+OnFailure=emergency.target
+OnFailureJobMode=replace-irreversibly
+DefaultDependencies=no
+Conflicts=shutdown.target
diff --git a/units/initrd.target b/units/initrd.target
index eae7c703c1..8be7e2b399 100644
--- a/units/initrd.target
+++ b/units/initrd.target
@@ -12,6 +12,6 @@ OnFailure=emergency.target
OnFailureJobMode=replace-irreversibly
ConditionPathExists=/etc/initrd-release
Requires=basic.target
-Wants=initrd-root-fs.target initrd-fs.target initrd-parse-etc.service
-After=initrd-root-fs.target initrd-fs.target basic.target rescue.service rescue.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
AllowIsolate=yes