diff options
author | Helmut Grohne <helmut@subdivi.de> | 2025-03-30 15:56:12 +0200 |
---|---|---|
committer | Helmut Grohne <helmut@subdivi.de> | 2025-03-30 16:19:51 +0200 |
commit | 5c0e89a0a97a3d802bc990173fde5c309bfac002 (patch) | |
tree | c315a21502936e14030ff26d8db5f6a84d03044f | |
parent | 695c2e7b2a5e82b7e50b8472a6649584fa9406f1 (diff) | |
download | debvm-5c0e89a0a97a3d802bc990173fde5c309bfac002.tar.gz |
debvm-create: work around arm32 boot failure
The long story of this commit can be found in #1079443. Special thanks
to all of the following for investing significant amounts of time into
debugging the root cause:
* Tj <tj.iam.tj@proton.me>
* Jochen Sprickerhof <jspricke@debian.org>
* Chris Hofstaedtler <zeha@debian.org>
In the end, dracut-install fails to install kernel modules (including
virtio_blk) that are being passed as =directory if said directory has an
inode number exceeding 32bit on an arm32 userland. Lots of thought has
been expended into fixing fts on the glibc side with little conclusions.
Since armhf is still somewhat important, we settle on a workaround here.
The problem is acknowledged and we explicitly install the virtio_blk
kernel module that dracut-install should have installed. Doing so at
least makes the debvm boot.
For reproducing the problem, TMPDIR needs to point to a directory where
created directories receive inodes exceeding 32bit. On a tmpfs, this
situation can be achieved by creating and deleting lots of directories.
The following code can be run in parallel to increase the inode counter
in a couple of hours:
#include <sys/stat.h>
#include <unistd.h>
int main(int argc, char **argv) {
for(;;) {
mkdir(argv[1], 0755);
rmdir(argv[1]);
}
}
-rwxr-xr-x | share/customize-kernel.sh | 55 |
1 files changed, 52 insertions, 3 deletions
diff --git a/share/customize-kernel.sh b/share/customize-kernel.sh index d216eaa..0a252a4 100755 --- a/share/customize-kernel.sh +++ b/share/customize-kernel.sh @@ -8,14 +8,52 @@ set -eu +if [ "${MMDEBSTRAP_VERBOSITY:-1}" -ge 3 ]; then + set -x +fi + TARGET="$1" +ARCHITECTURES=$(xargs < "$TARGET/var/lib/dpkg/arch") + +affected_by_1079443() { + case "${ARCHITECTURES%% *}" in + armel|armhf) + ;; + *) + return 1 + ;; + esac + test "${1:-}" = --maybe && return 0 + test -d "$TARGET/etc/initramfs-tools/hooks" || return 1 + dpkg-query --root="$TARGET" --showformat='${db:Status-Status}\n' --show dracut-install 2>/dev/null | grep -q '^installed$' +} +work_around_1079443() { + # FTS or its usage in dracut-install is broken on some 32bit architectures. + echo "Warning: working around #1079443" + cat >"$TARGET/etc/initramfs-tools/hooks/work_around_1079443" <<'EOF' +#!/bin/sh + +test "${1-}" = prereqs && exit 0 + +. /usr/share/initramfs-tools/hook-functions + +# work around #1079443 +manual_add_modules virtio_blk +EOF + chmod +x "$TARGET/etc/initramfs-tools/hooks/work_around_1079443" + if test "${1:-}" = --update && test -x "$TARGET/usr/bin/update-initramfs"; then + chroot "$TARGET/update-initramfs -u" + fi +} + if dpkg-query --root="$TARGET" --showformat='${db:Status-Status}\n' --show 'linux-image-*' 2>/dev/null | grep -q '^installed$'; then + if affected_by_1079443; then + work_around_1079443 --update + fi exit 0 fi -ARCHITECTURES=$(xargs < "$TARGET/var/lib/dpkg/arch") - KERNEL_ARCH="${ARCHITECTURES%% *}" case "$KERNEL_ARCH" in armel) @@ -70,4 +108,15 @@ else fi # On some derivatives such as Ubuntu, linux image does not depend on an initramfs. -apt-get --yes satisfy "$@" "linux-image-cloud-$KERNEL_ARCH | linux-image-$KERNEL_ARCH | linux-image-generic" "initramfs-tools | linux-initramfs-tool" +KERNEL_SATISFY="linux-image-cloud-$KERNEL_ARCH | linux-image-$KERNEL_ARCH | linux-image-generic" +INITRD_SATISFY="initramfs-tools | linux-initramfs-tool" + +if affected_by_1079443 --maybe; then + apt-get --yes satisfy "$@" "$INITRD_SATISFY" + if affected_by_1079443; then + work_around_1079443 + fi + apt-get --yes satisfy "$@" "$KERNEL_SATISFY" +else + apt-get --yes satisfy "$@" "$KERNEL_SATISFY" "$INITRD_SATISFY" +fi |