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