fix(dracut-install): build with -Werror=discarded-qualifiers
```
src/install/dracut-install.c:475:11: error: assignment discards 'const' qualifier from pointer target type [-Werror=discarded-qualifiers]
475 | q = strstr(lib, ".so.");
```
- `q` cannot be const, because it's also used for `q = strstr(clib, ".so.");`,
removing the suffix from clib via `q[3] = '\0';`, so create two variables to get
the suffix offsets, one const for `lib`, other non-const for `clib`.
```
src/install/dracut-install.c:2592:11: error: assignment discards 'const' qualifier from pointer target type [-Werror=discarded-qualifiers]
2592 | p = strstr(abskpath, "/lib/modules/");
```
- `p` can be const like `abskpath`, since it's not modified.
Jens Schmidt [Sat, 22 Nov 2025 20:15:24 +0000 (21:15 +0100)]
fix(functions): do not use path escapes for non-paths
Function dev_unit_name unconditionally calls `systemd-escape -p` on the device
argument, even if that is a non-path, for example, a LUKS UUID.
`systemd-escape -p` writes a warning for non-paths, so just use plain
`systemd-escape` for these.
Benjamin Drung [Tue, 25 Nov 2025 23:16:43 +0000 (00:16 +0100)]
test(run-qemu): support UEFI on ARM
The OVMF firmware files are builds of EDK II for 64-bit x86 virtual
machines. They do not work on other architectures.
So search for AAVMF files on ARM. Remove the `cfi.pflash01` driver
setting because it does not work on Ubuntu arm64 and `readonly=on` is
already set for the firmware file.
Benjamin Drung [Sat, 8 Nov 2025 13:54:43 +0000 (14:54 +0100)]
test: determine rootfs size dynamically
Do not hard-code the size of the rootfs, but determine the needed size
dynamically. This will speed up the creation time for smaller content
and prevent failures in case of bigger content.
Inode numbers are unique (for non-hardlinks) within the archive, so
device ID mapping is unnecessary. Confirm that dracut-cpio behaves like
GNU cpio --ignore-devno. Check this by archiving the /tmp directory
alongside a working-directory nested file; despite differing source
device IDs, the archived major/minor numbers should be zero.
The test is skipped if stat(/tmp) fails, or working-directory and /tmp
device ids match.
initramfs / cpio allow for the tracking of hardlinks for nlink >= 2
entries using a combination of the inode, device major and minor
numbers.
dracut-cpio uses unique inode numbers within an archive via the global
state.ino counter. Device major/minor numbers are also renumbered, with
each unique source device obtaining a major/minor number mapped from the
index within dev_seen()/DevState array.
With archive-unique inode numbers, device major/minor mapping is
unnecessary. This change sees dracut-cpio behave the same as GNU
cpio --ignore-devno, where archive device major/minor numbers are
hardcoded to zero.
Hardlink tracking is simplified, replacing per-device HardlinkState
arrays with a global state.hls array. A hash could be used for faster
source inode+dev -> archive HardlinkState mapping, but the extra
size and complexity isn't worth it IMO, given that hardlinks should be
rare.
A typo that I made in the initial dracut-cpio implementation sees the
stat()-dev_t-derived major number used for both major and minor number
in the cpio archive.
This bug shouldn't cause any real-world issues, as archive-renumbered
inode numbers are already unique and hardlink tracking checks against
the proper dev_t tuple.
Benjamin Drung [Tue, 18 Nov 2025 18:34:52 +0000 (19:34 +0100)]
test: replace rev command by sed
On Debian-based systems, the `rev` command is shipped by the
bsdextrautils package. Replace the `rev` command by `sed` which is an
essential command and does not need additional packages.
feat(network-manager): add systemd generator if available
A systemd generator was added in [1] to fix an upstream issue [2]. It also
brings the removal of the "[Install]" section from the upstream initrd services;
it is used to mask the initrd services on the host, and to mask the host
services and provide installation links of the initrd services in the initrd.
Additionally, increase the minimum NetworkManager version set to remove custom
systemd services from dracut.
Benjamin Drung [Wed, 19 Nov 2025 03:28:38 +0000 (04:28 +0100)]
test: set console cmdline depending on the architecture
The QEMU process hangs (without printing anything) on some Debian/Ubuntu
architectures. This is caused by the console device is called
differently on those architectures.
So move setting `console` to `run-qemu` and set it to `ttyAMA0` on ARM
systems and to `hvc0` on ppc64el.
fix(nfs): set the default group of the rpcbind user to the state dir
Commit 4a236f015905f598e2976ae6f0f460ec9a567f2b sets the fixed "root" group to
`/run/rpcbind`, but it can be different depending on the distribution (for
example, `rpc` in openSUSE and Fedora).
perf(nfs): remove references to old rpcbind state dir
The default state directory (needed by `rpcbind` to save warm start info) was
initially `/tmp`, but it can be configured with `--with-statedir=` since [1].
This default state directory changed to a more appropriate `/var/run` [2], and
then explicitly to `/run` [3].
So, `/var/lib/rpcbind` existed when this dracut module was created because RH/
Fedora had it configured with `--with-statedir=`, like openSUSE until 2016 [4]
fix(dracut-systemd): use expected PS1 in the emergency shell
Before starting `dracut-emergency.service`, the function `_emergency_shell()`
writes `PS1` to `/etc/profile`. Then `/etc/profile` is sourced in
`dracut-emergency.sh`, but `PS1` is not exported, so the current hook name is
never displayed in the emergency shell. Also, the default name "dracut" is not
printed either in the fallback `PS1`, because the variable `_name` is not set;
it should be `_rdshell_name`.
Jo Zzsi [Sat, 1 Nov 2025 23:20:42 +0000 (19:20 -0400)]
feat: rename rd.live.overlay.overlayfs to rd.overlayfs
The overlayfs dracut module can be used without the dmsquash-live
dracut module. This change improves on naming of command line options
with better namespace scoping.
Move overlayfs documentation out of the live images section.
Benjamin Drung [Sat, 1 Nov 2025 10:49:33 +0000 (11:49 +0100)]
test: drop requiring iscsiuio.socket
The iscsiuio socket/service is only needed on specific hardware. It is
not needed for the ISCSI and ISCSI-MULTI test cases. Without this check
the tests will succeed on Debian and Ubuntu.
Benjamin Drung [Sat, 1 Nov 2025 03:23:59 +0000 (04:23 +0100)]
fix(iscsi): modify iscsid.service in initrd instead of host
Commit b2287bb7c4544d841b3d5b0510ce765753d990af ("fix(iscsi): drop
ExecStartPre startup-checks.sh from iscsid.service") incorrectly
modifies `iscsid.service` on the host instead of the service that was
copied into the initrd.
Corretly modify `iscsid.service` in initrd instead of on the host.
Daniel Hast [Fri, 31 Oct 2025 13:06:17 +0000 (09:06 -0400)]
fix: line-buffer log output to /dev/kmsg
/dev/kmsg is only designed to accept single lines at a time, and
therefore has a relatively small message size limit. This means we need
to line-buffer the output of awk (and prepend the message level prefix
to each line rather than just the first).
Signed-off-by: Daniel Hast <hast.daniel@protonmail.com>
Jo Zzsi [Fri, 10 Oct 2025 12:45:07 +0000 (08:45 -0400)]
feat(kernel-modules-export): make kernel modules from initramfs available
Although the kernel module for the filesystem is in the initramfs,
it might not loaded in the initramfs, because it is not needed to mount
the root filesystem.
This feature arranges for the kernel modules in the initramfs to be
placed into /lib/modules.
When booting with an external-to-rootfs kernel you need to ensure that
/lib/modules contains any necessary modules not already loaded.
There is no overlay directory for the server initrd. Commit c855fa1ee5c0f01da91bb7724c9dd2f4adb3b50e ("test(NFS): drop including
missing overlay in server initrd") fixed it for test 60. So do the same
for these tests.
Benjamin Drung [Fri, 31 Oct 2025 11:42:39 +0000 (12:42 +0100)]
fix(dracut-systemd): install grep if initqueue is used
TEST-13-SYSROOT emits this error on Ubuntu:
```
dracut-initqueue[248]: /usr/bin/dracut-initqueue: 1: /lib/dracut/hooks/initqueue/finished/devexists-\x2fdev\x2fdisk\x2fby-label\x2fdracut.sh: grep: not found
```
`parse-root.sh` injects a grep call into
`$hookdir/initqueue/finished/devexists-${root_name}.sh`. Therefore the
`grep` command needs to be installed if initqueue is used.
multipath-tools 0.9.8 added a new udev rules file that restores
DM_UDEV_DISABLE_OTHER_RULES_FLAG before saving properties to the
udev db [1]. This fixes a few corner cases that can arise with
LVM2 < 2.03.24 if uevents occur for previously suspended devices.
This rule will do nothing, unless DM_UDEV_DISABLE_OTHER_RULES_FLAG
has been previously modified by 11-dm-mpath.rules.
While it's rather unlikely that this situation occurs during initrd
processing, add the rule file if present, to make sure the multipath
udev rule set is complete and consistent.
Daniel Hast [Thu, 30 Oct 2025 16:30:51 +0000 (12:30 -0400)]
perf: improve logger efficiency
The logger would previously feed input from stdin one line at a time to
the logging target. This is very slow and can have a major impact on
performance when dealing with debug output that can be thousands of
lines long, such as the output of `lsinitrd`.
Instead, add a `_do_dlog_batch` function that accepts input on stdin
rather than as an argument, splits stdin into multiple streams, and uses
`awk` to process multiline inputs efficiently for each target. When
`dlog` is called without arguments, it passes stdin on to this function.
This is orders of magnitude faster for large inputs.
Signed-off-by: Daniel Hast <hast.daniel@protonmail.com>
Daniel Hast [Thu, 30 Oct 2025 16:27:37 +0000 (12:27 -0400)]
fix: make logging functions return 1 only on invalid log level
Change the internal logging functions to return 0 if given a valid log
level and 1 if given an invalid log level, and document this.
The previously documented return value was inaccurate: `_do_dlog` would
not always return 0 as claimed, but rather would return 1 if
`lvl <= kmsgloglvl` due to using `&&` rather than an `if` block for the
final conditional.
Signed-off-by: Daniel Hast <hast.daniel@protonmail.com>
Benjamin Drung [Wed, 29 Oct 2025 20:40:22 +0000 (21:40 +0100)]
feat(plymouth): drop unused plymouth-populate-initrd
The plymouth `check` function calls `pkglib_dir` which searches for an
executable `plymouth-populate-initrd` script. Otherwise it will exit
with a failure and plymouth will not be included. Therefore
`plymouth-populate-initrd` will always be present when `install` is
called. Thus the code path for calling `plymouth-populate-initrd.sh`
will never taken.
So drop `plymouth-populate-initrd.sh` and its unused code path.
Benjamin Drung [Thu, 30 Oct 2025 11:53:27 +0000 (12:53 +0100)]
fix(Makefile): correct filter condition for s390 specific modules
Commit fe6c47025516fe9705fa0fb621b381ce85d5127c ("feat(Makefile): filter
out s390 specific dracut modules") want to exclude s390 specific dracut
modules but got the condition inversed.
Koen Kooi [Thu, 19 Jun 2025 14:06:14 +0000 (16:06 +0200)]
feat: dracut.sh: try $STRIP for $strip_cmd first
When using dracut in a cross enviroment, like OpenEmbedded, the host
provided strip (or eu-strip) won't work, so try using the $STRIP
variable from the shell environment first before falling back to path
based lookups.
Benjamin Drung [Thu, 30 Oct 2025 11:14:06 +0000 (12:14 +0100)]
refactor(test): introduce build_ext4_image function
Building an ext4 rootfs image from a directory is done in multiple test
cases. Move those code into a single `build_ext4_image` helper function
to reduce code duplication.
Benjamin Drung [Wed, 29 Oct 2025 16:08:07 +0000 (17:08 +0100)]
test: drop do_hardlink=no from test-makeroot and test-root
TEST-60-NFS fails booting `initramfs.makeroot` on Ubuntu resolute:
```
[ 2.147915] Kernel panic - not syncing: System is deadlocked on memory
```
The virtual machine has only 1 GB memory. The `initramfs.makeroot` is
601 MB in size. Over half of that size can be explained by using rust
coreutils in combination with `do_hardlink=no`:
The coreutils binary is 10 MB in size and duplicated 11 times plus the
same for `source` and `source/nfs/client`. Resulting in 357 MB.
Using `do_hardlink=yes` will reduce the initrd size from 601 MB to
123 MB. So drop `do_hardlink=no` from the `test-makeroot` and
`test-root` configuration files.
Flos Lonicerae [Sat, 11 Oct 2025 17:45:47 +0000 (01:45 +0800)]
feat(skipcpio): output additional CPIO information
Provides additional CPIO information to skipcpio, allowing users to
better understand the composition of the split file. To display the
results we'll use an environment variable 'DEBUG_SKIPCPIO' as a switch.
turret [Sun, 26 Oct 2025 22:56:44 +0000 (17:56 -0500)]
fix(base): set udev log level properly
since udev logging functionality was added in af67d62 to dracut,
in commit 25e773eeb4 in systemd, udev has since migrated from its own
logging system to the logging system found in the rest of systemd, which
uses a different environment variable for setting the log level. this
will allow for systems to truely be quiet during boot (i.e., before
showing a splash or before the init system begins being loud)
instead of using the systemd-specific environment variable, we set it in
udev.conf so that the change also applies to eudev-and-friends
hilariously, udev did the migration the day after dracut added support!
if systems were kept up to date with live branches, that means the
original change would have only worked for one day.
fix(network-manager): hostname not set with old systemd service units
Commit 83dffc58f606ad7ad47a32716ce240831d7f018f added support for using the new
systemd services provided by NetworkManager upstream if available, instead of
the old custom systemd services provided by dracut. Specifically,
`NetworkManager-config-initrd.service` sets /proc/sys/kernel/hostname if needed,
that's why the old code doing this in the initqueue hook `nm-run.sh` was
moved by mistake to the section that is executed when systemd is not present.
Benjamin Drung [Wed, 29 Oct 2025 11:27:13 +0000 (12:27 +0100)]
fix(systemd-networkd): correct path of 99-default.network on hostonly=no
Commit 2991f74ab46389947ce8f96b87a7abdc1862cbb6 ("chore(dracut): enforce
that /etc is only used in hostonly mode") does not set
`systemdnetworkconfdir` any more on `hostonly=no`. This causes the
systemd-network module to install `99-default.network` to
`/zzzz-dracut-default.network` on generic builds and therefore loosing
this network config.
Install `99-default.network` to the system path in `/usr` instead.
Coiby Xu [Thu, 16 Oct 2025 07:43:05 +0000 (15:43 +0800)]
fix(dracut): use grep -q/-s to silence output/error
There is no need to redirect output/error to /dev/null. Simply use -q/-s
option provided by grep.
Note we should use avoid using
"set -o pipefail lsinitrd PAHT_PATH_INITRAMFS | grep -q PATTERN".
Because with set -o pipefail, a pipeline’s exit status becomes non-zero
if any element of the pipeline fails and grep -q exits as soon as it
sees a match.
Benjamin Drung [Wed, 29 Oct 2025 01:22:24 +0000 (02:22 +0100)]
test: show all server logs until the "Serving" line
The function `wait_for_server_startup` will search för `Serving` in the
server log for the indication that the server started correctly. It will
print the logs every second until `Serving` is found, but it will not
print the `Serving` line.
Print the remaining log lines after `Serving` has been found.
Benjamin Drung [Wed, 29 Oct 2025 00:58:11 +0000 (01:58 +0100)]
test(NFS): do not ignore failures in test_nfsv3
After `set -e` is called, the shell will exit immediately if a simple
command exits with a non-zero status, but the shell will not exit if the
command is part of a `&&` list.
So calling `test_nfsv3 && test_nfsv4` will not exit on failures in
`test_nfsv3`. Call those functions separately and rely on `set -e`.
Benjamin Drung [Tue, 28 Oct 2025 13:13:28 +0000 (14:13 +0100)]
test: support systemd in target rootfs
The test-root module installs `test-init.sh` in `/sbin/test-init` and
adds `testsuite.service` if systemd is used. When systemd is used in the
target client/server rootfs, the systemd in the initrd hands over the
control to the systemd in the rootfs. Then `testsuite.service` executes
`test-init.sh` instead of the wanted client/server init scripts.
Add the helper function `inst_init` to override the init script from the
test-root dracut module.
Benjamin Drung [Wed, 8 Oct 2025 20:03:46 +0000 (22:03 +0200)]
feat(plymouth): do not check plymouth-populate-initrd for "nash"
Commit f9749f368f1e ("plymouth: use
/usr/libexec/plymouth/plymouth-populate-initrd if possible") checked
`plymouth-populate-initrd` not not contain `nash` in 2009. The current
Plymouth version does not contain this string and there were no reason
given for this check.
Drop checking `plymouth-populate-initrd` for not containing `nash`.
Benjamin Drung [Mon, 11 Aug 2025 17:22:49 +0000 (19:22 +0200)]
fix(lsinitrd): drop --verbose from cpio --to-stdout call
Calling `cpio --extract` with `--verbose` will print the filenames to
stderr, but this output is thrown away. Calling `cpio --extract --quiet`
will not print anything on stderr (except for error messages).
So drop `--verbose` and then stderr does not need to be thrown away any
more.
Jo Zzsi [Wed, 8 Oct 2025 13:26:40 +0000 (09:26 -0400)]
test(UEFI): no longer needs to run inside a container
Commit 82cd3d3 allows changing the dracut configuration using the
/run/initramfs/dracut.conf.d directory without modifying the
/etc or /usr directories.
This new dracut feature allows running this test on bare metal.
Remove the check for running inside a container that was left
in this test inadvertently.
Benjamin Drung [Tue, 28 Oct 2025 15:50:54 +0000 (16:50 +0100)]
fix(iscsi): drop ExecStartPre startup-checks.sh from iscsid.service
`/usr/lib/open-iscsi/startup-checks.sh` checks that
`/etc/iscsi/iscsid.conf` and `/etc/iscsi/initiatorname.iscsi` are
present. This is not the case for initrds built without hostonly.
So just drop `/usr/lib/open-iscsi/startup-checks.sh` from
`iscsid.service` and rely on dracut to generate a working environment
for iscsid.
Benjamin Drung [Tue, 21 Oct 2025 17:18:28 +0000 (19:18 +0200)]
test: fix catching failures with "set -e" in tests
After `set -e` is called, the shell will exit immediately if a simple
command exits with a non-zero status, but the shell will not exit if the
command is part of a `&&` list.
So calling `test_setup && test_run` will not exit on failures in
`test_setup`. Failures in `test_run` will cause the script to exit
without printing the result.
Restructure the test runner to rely on `set -e` aborting the test and
use a trap on this error to print the test result.