From 7163e1ca1108d789ee8b40238ebf0f6978cd58a9 Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Thu, 12 May 2016 10:42:39 -0600 Subject: [PATCH] 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). --- Makefile.am | 1 + man/bootup.xml | 7 ++++++- man/systemd.special.xml | 13 +++++++++++++ src/basic/special.h | 1 + src/fstab-generator/fstab-generator.c | 8 ++++++++ src/gpt-auto-generator/gpt-auto-generator.c | 6 ++++++ src/shared/generator.c | 16 +++++++++++++++- src/shared/generator.h | 4 ++++ units/initrd-root-device.target | 15 +++++++++++++++ units/initrd.target | 4 ++-- 10 files changed, 71 insertions(+), 4 deletions(-) create mode 100644 units/initrd-root-device.target diff --git a/Makefile.am b/Makefile.am index aea91e9c948..c126f65ad2b 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 b92057af294..986996398cc 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 14998b9647d..26974ed73fc 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 2fd03d9f757..084d3dfa23c 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 343e3b18179..108522873e8 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 af96adec068..a4938a7c3a6 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 cd3c35cd550..70afc6a285b 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 a734e139700..a6017c1b76a 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 00000000000..9d44d2d3039 --- /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 eae7c703c16..8be7e2b3994 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