Create initrd-root-device.target synchronization point (#3239)

Add a synchronization point so that custom initramfs units can run
after the root device becomes available, before it is fsck'd and
mounted.

This is useful for custom initramfs units that may modify the
root disk partition table, where the root device is not known in
advance (it's dynamically selected by the generators).
This commit is contained in:
Daniel Drake 2016-05-12 10:42:39 -06:00 committed by Lennart Poettering
parent 42d35e1301
commit 7163e1ca11
10 changed files with 71 additions and 4 deletions

View File

@ -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 \

View File

@ -179,6 +179,8 @@
identical to the system manager bootup (see above) until it
reaches <filename>basic.target</filename>. From there, systemd
approaches the special target <filename>initrd.target</filename>.
When the root device becomes available,
<filename>initd-root-device.target</filename> is reached.
If the root device can be mounted at
<filename>/sysroot</filename>, the
<filename>sysroot.mount</filename> unit becomes active and
@ -204,7 +206,10 @@
| emergency.service
______________________/| |
/ | v
| sysroot.mount <emphasis>emergency.target</emphasis>
| initrd-root-device.target <emphasis>emergency.target</emphasis>
| |
| v
| sysroot.mount
| |
| v
| initrd-root-fs.target

View File

@ -83,6 +83,7 @@
<filename>remote-fs.target</filename>,
<filename>remote-fs-pre.target</filename>,
<filename>rescue.target</filename>,
<filename>initrd-root-device.target</filename>,
<filename>initrd-root-fs.target</filename>,
<filename>rpcbind.target</filename>,
<filename>runlevel2.target</filename>,
@ -464,6 +465,18 @@
SysV.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><filename>initrd-root-device.target</filename></term>
<listitem>
<para>A special initrd target unit that is reached when the root filesystem device is available, but before
it has been mounted.
<citerefentry><refentrytitle>systemd-fstab-generator</refentrytitle><manvolnum>3</manvolnum></citerefentry>
and
<citerefentry><refentrytitle>systemd-gpt-auto-generator</refentrytitle><manvolnum>3</manvolnum></citerefentry>
automatically setup the appropiate dependencies to make this happen.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><filename>initrd-root-fs.target</filename></term>
<listitem>

View File

@ -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"

View File

@ -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,

View File

@ -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",

View File

@ -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);
}

View File

@ -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);

View File

@ -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

View File

@ -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