Merge pull request #208269 from ElvishJerricco/systemd-stage-1-fsck

Systemd stage 1 fsck
This commit is contained in:
Florian Klink 2023-02-17 10:06:39 +02:00 committed by GitHub
commit ab566b8656
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 91 additions and 36 deletions

View file

@ -158,6 +158,16 @@ in {
'';
};
managerEnvironment = mkOption {
type = with types; attrsOf (nullOr (oneOf [ str path package ]));
default = {};
example = { SYSTEMD_LOG_LEVEL = "debug"; };
description = lib.mdDoc ''
Environment variables of PID 1. These variables are
*not* passed to started units.
'';
};
contents = mkOption {
description = lib.mdDoc "Set of files that have to be linked into the initrd";
example = literalExpression ''
@ -355,8 +365,11 @@ in {
less = "${pkgs.less}/bin/less";
mount = "${cfg.package.util-linux}/bin/mount";
umount = "${cfg.package.util-linux}/bin/umount";
fsck = "${cfg.package.util-linux}/bin/fsck";
};
managerEnvironment.PATH = "/bin:/sbin";
contents = {
"/init".source = "${cfg.package}/lib/systemd/systemd";
"/etc/systemd/system".source = stage1Units;
@ -365,6 +378,7 @@ in {
[Manager]
DefaultEnvironment=PATH=/bin:/sbin ${optionalString (isBool cfg.emergencyAccess && cfg.emergencyAccess) "SYSTEMD_SULOGIN_FORCE=1"}
${cfg.extraConfig}
ManagerEnvironment=${lib.concatStringsSep " " (lib.mapAttrsToList (n: v: "${n}=${lib.escapeShellArg v}") cfg.managerEnvironment)}
'';
"/lib/modules".source = "${modulesClosure}/lib/modules";
@ -447,21 +461,6 @@ in {
(v: let n = escapeSystemdPath v.where;
in nameValuePair "${n}.automount" (automountToUnit n v)) cfg.automounts);
# The unit in /run/systemd/generator shadows the unit in
# /etc/systemd/system, but will still apply drop-ins from
# /etc/systemd/system/foo.service.d/
#
# We need IgnoreOnIsolate, otherwise the Requires dependency of
# a mount unit on its makefs unit causes it to be unmounted when
# we isolate for switch-root. Use a dummy package so that
# generateUnits will generate drop-ins instead of unit files.
packages = [(pkgs.runCommand "dummy" {} ''
mkdir -p $out/etc/systemd/system
touch $out/etc/systemd/system/systemd-{makefs,growfs}@.service
'')];
services."systemd-makefs@" = lib.mkIf needMakefs { unitConfig.IgnoreOnIsolate = true; };
services."systemd-growfs@" = lib.mkIf needGrowfs { unitConfig.IgnoreOnIsolate = true; };
# make sure all the /dev nodes are set up
services.systemd-tmpfiles-setup-dev.wantedBy = ["sysinit.target"];

View file

@ -140,7 +140,10 @@ let
else if config.fsType == "reiserfs" then "-q"
else null;
in {
options = mkIf config.autoResize [ "x-nixos.autoresize" ];
options = mkMerge [
(mkIf config.autoResize [ "x-nixos.autoresize" ])
(mkIf (utils.fsNeededForBoot config) [ "x-initrd.mount" ])
];
formatOptions = mkIf (defaultFormatOptions != null) (mkDefault defaultFormatOptions);
};
@ -155,27 +158,54 @@ let
makeFstabEntries =
let
fsToSkipCheck = [ "none" "bindfs" "btrfs" "zfs" "tmpfs" "nfs" "nfs4" "vboxsf" "glusterfs" "apfs" "9p" "cifs" "prl_fs" "vmhgfs" ];
fsToSkipCheck = [
"none"
"auto"
"overlay"
"iso9660"
"bindfs"
"udf"
"btrfs"
"zfs"
"tmpfs"
"bcachefs"
"nfs"
"nfs4"
"nilfs2"
"vboxsf"
"squashfs"
"glusterfs"
"apfs"
"9p"
"cifs"
"prl_fs"
"vmhgfs"
] ++ lib.optionals (!config.boot.initrd.checkJournalingFS) [
"ext3"
"ext4"
"reiserfs"
"xfs"
"jfs"
"f2fs"
];
isBindMount = fs: builtins.elem "bind" fs.options;
skipCheck = fs: fs.noCheck || fs.device == "none" || builtins.elem fs.fsType fsToSkipCheck || isBindMount fs;
# https://wiki.archlinux.org/index.php/fstab#Filepath_spaces
escape = string: builtins.replaceStrings [ " " "\t" ] [ "\\040" "\\011" ] string;
in fstabFileSystems: { rootPrefix ? "", excludeChecks ? false, extraOpts ? (fs: []) }: concatMapStrings (fs:
in fstabFileSystems: { rootPrefix ? "", extraOpts ? (fs: []) }: concatMapStrings (fs:
(optionalString (isBindMount fs) (escape rootPrefix))
+ (if fs.device != null then escape fs.device
else if fs.label != null then "/dev/disk/by-label/${escape fs.label}"
else throw "No device specified for mount point ${fs.mountPoint}.")
+ " " + escape (rootPrefix + fs.mountPoint)
+ " " + escape fs.mountPoint
+ " " + fs.fsType
+ " " + escape (builtins.concatStringsSep "," (fs.options ++ (extraOpts fs)))
+ " " + (optionalString (!excludeChecks)
("0 " + (if skipCheck fs then "0" else if fs.mountPoint == "/" then "1" else "2")))
+ " 0 " + (if skipCheck fs then "0" else if fs.mountPoint == "/" then "1" else "2")
+ "\n"
) fstabFileSystems;
initrdFstab = pkgs.writeText "initrd-fstab" (makeFstabEntries (filter utils.fsNeededForBoot fileSystems) {
rootPrefix = "/sysroot";
excludeChecks = true;
extraOpts = fs:
(optional fs.autoResize "x-systemd.growfs")
++ (optional fs.autoFormat "x-systemd.makefs");
@ -328,7 +358,9 @@ in
)}
'';
boot.initrd.systemd.contents."/etc/fstab".source = initrdFstab;
boot.initrd.systemd.storePaths = [initrdFstab];
boot.initrd.systemd.managerEnvironment.SYSTEMD_SYSROOT_FSTAB = initrdFstab;
boot.initrd.systemd.services.initrd-parse-etc.environment.SYSTEMD_SYSROOT_FSTAB = initrdFstab;
# Provide a target that pulls in all filesystems.
systemd.targets.fs =

View file

@ -1084,15 +1084,17 @@ in
what = "overlay";
type = "overlay";
options = "lowerdir=/sysroot/nix/.ro-store,upperdir=/sysroot/nix/.rw-store/store,workdir=/sysroot/nix/.rw-store/work";
wantedBy = ["local-fs.target"];
before = ["local-fs.target"];
requires = ["sysroot-nix-.ro\\x2dstore.mount" "sysroot-nix-.rw\\x2dstore.mount" "rw-store.service"];
after = ["sysroot-nix-.ro\\x2dstore.mount" "sysroot-nix-.rw\\x2dstore.mount" "rw-store.service"];
unitConfig.IgnoreOnIsolate = true;
wantedBy = ["initrd-fs.target"];
before = ["initrd-fs.target"];
requires = ["rw-store.service"];
after = ["rw-store.service"];
unitConfig.RequiresMountsFor = "/sysroot/nix/.ro-store";
}];
services.rw-store = {
after = ["sysroot-nix-.rw\\x2dstore.mount"];
unitConfig.DefaultDependencies = false;
unitConfig = {
DefaultDependencies = false;
RequiresMountsFor = "/sysroot/nix/.rw-store";
};
serviceConfig = {
Type = "oneshot";
ExecStart = "/bin/mkdir -p 0755 /sysroot/nix/.rw-store/store /sysroot/nix/.rw-store/work /sysroot/nix/store";

View file

@ -234,6 +234,7 @@ in {
freshrss-pgsql = handleTest ./freshrss-pgsql.nix {};
frr = handleTest ./frr.nix {};
fsck = handleTest ./fsck.nix {};
fsck-systemd-stage-1 = handleTest ./fsck.nix { systemdStage1 = true; };
ft2-clone = handleTest ./ft2-clone.nix {};
mimir = handleTest ./mimir.nix {};
garage = handleTest ./garage {};

View file

@ -1,3 +1,9 @@
{ system ? builtins.currentSystem
, config ? {}
, pkgs ? import ../.. { inherit system config; }
, systemdStage1 ? false
}:
import ./make-test-python.nix {
name = "fsck";
@ -11,13 +17,17 @@ import ./make-test-python.nix {
autoFormat = true;
};
};
boot.initrd.systemd.enable = systemdStage1;
};
testScript = ''
machine.wait_for_unit("default.target")
with subtest("root fs is fsckd"):
machine.succeed("journalctl -b | grep 'fsck.ext4.*/dev/vda'")
machine.succeed("journalctl -b | grep '${if systemdStage1
then "fsck.*vda.*clean"
else "fsck.ext4.*/dev/vda"}'")
with subtest("mnt fs is fsckd"):
machine.succeed("journalctl -b | grep 'fsck.*/dev/vdb.*clean'")

View file

@ -4,19 +4,30 @@ Date: Thu, 1 May 2014 14:10:10 +0200
Subject: [PATCH] Look for fsck in the right place
---
src/fsck/fsck.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
src/fsck/fsck.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/src/fsck/fsck.c b/src/fsck/fsck.c
index 595434ab57..374a4e6c76 100644
index 73c76fceea..d00cea7158 100644
--- a/src/fsck/fsck.c
+++ b/src/fsck/fsck.c
@@ -373,7 +373,7 @@ static int run(int argc, char *argv[]) {
@@ -352,6 +352,7 @@ static int run(int argc, char *argv[]) {
if (r == 0) {
char dash_c[STRLEN("-C") + DECIMAL_STR_MAX(int) + 1];
int progress_socket = -1;
+ _cleanup_free_ char *fsck_name = NULL;
const char *cmdline[9];
int i = 0;
@@ -372,7 +373,10 @@ static int run(int argc, char *argv[]) {
} else
dash_c[0] = 0;
- cmdline[i++] = "/sbin/fsck";
+ cmdline[i++] = "/run/current-system/sw/bin/fsck";
+ r = find_executable("fsck", &fsck_name);
+ if (r < 0)
+ return r;
+ cmdline[i++] = fsck_name;
cmdline[i++] = arg_repair;
cmdline[i++] = "-T";