name: Kernel Version Test
on:
workflow_call:
inputs:
kernel_version:
description: 'Version of the Linux kernel to build'
required: true
type: string
jobs:
build:
runs-on: ubuntu-latest
env:
KERNEL_VERSION: ${{ inputs.kernel_version }}
steps:
- uses: actions/checkout@v4
- name: Install system dependencies
run: |
sudo apt-get update
sudo apt-get install -y \
bison flex libelf-dev \
qemu-system-x86 busybox-static cpio xz-utils wget e2fsprogs
- name: Create ext4 test disk
run: |
dd if=/dev/zero of=disk.img bs=1M count=64
mkfs.ext4 -F disk.img
- name: Cache Linux source
id: cache-kernel
uses: actions/cache@v4
with:
path: linux-${{ env.KERNEL_VERSION }}
key: kernel-${{ env.KERNEL_VERSION }}
- name: Download & build Linux kernel
if: steps.cache-kernel.outputs.cache-hit != 'true'
run: |
MAJOR=${KERNEL_VERSION%%.*}
wget https://cdn.kernel.org/pub/linux/kernel/v${MAJOR}.x/linux-${KERNEL_VERSION}.tar.xz
tar xf linux-${KERNEL_VERSION}.tar.xz
cd linux-${KERNEL_VERSION}
# Generate the default config
make defconfig
# Enable essentials as built-ins
scripts/config --enable CONFIG_DEVTMPFS
scripts/config --enable CONFIG_DEVTMPFS_MOUNT
# Enable virtio drivers, which is used by QEMU
scripts/config --enable CONFIG_VIRTIO
scripts/config --enable CONFIG_VIRTIO_PCI
scripts/config --enable CONFIG_VIRTIO_BLK
# Enable ext4 filesystem, as some tests require O_DIRECT operations
scripts/config --enable CONFIG_EXT4_FS
# Generate the updated config
make olddefconfig
make -j$(nproc)
- name: Generate the test binary
run: |
rustup target add x86_64-unknown-linux-musl
cargo build --package io-uring-test --features io-uring-test/ci --release --target x86_64-unknown-linux-musl
- name: Prepare initramfs + tests binaries
run: |
rm -rf initramfs && mkdir -p initramfs/{bin,sbin,proc,sys,tmp}
# Copy the test binary
cp target/x86_64-unknown-linux-musl/release/io-uring-test initramfs/bin/
# Add necessary binaries from busybox
cp /usr/bin/busybox initramfs/bin/
for cmd in sh mount ip ifconfig cat; do ln -sf busybox initramfs/bin/$cmd; done
ln -sf ../bin/busybox initramfs/sbin/poweroff
# Generate init script
cat > initramfs/init << 'EOF'
#!/bin/sh
set -e
# Activating the loopback interface (it's required for some network tests)
ip link set lo up
mkdir -p /dev
# Enable necessary devices
# https://www.kernel.org/doc/Documentation/admin-guide/devices.txt
mknod /dev/port c 1 4
mknod /dev/null c 1 3
mknod /dev/zero c 1 5
mknod /dev/tty c 5 0
mkdir -p /tmp && mount -t tmpfs -o mode=1777 tmpfs /tmp
# Bring up ext4 test volume at /mnt
mount -t devtmpfs devtmpfs /dev
mkdir -p /mnt
mount -t ext4 /dev/vda /mnt
# Run tests from a filesystem that supports O_DIRECT
cd /mnt
exit_code=0
# Run the test binary
RUST_BACKTRACE=1 /bin/io-uring-test || exit_code=1
# If the test binary exited with a non-zero code, write it to /dev/port.
# This lets QEMU exit with non-zero exit-code, triggering a CI error.
[ $exit_code -eq 0 ] || printf '\x01' \
| dd of=/dev/port bs=1 seek=244 count=1 2>/dev/null
/sbin/poweroff -f
EOF
chmod +x initramfs/init
# Pack into a CPIO archive
(cd initramfs && find . -print0 \
| cpio --null -ov --format=newc | gzip -9 > ../initramfs.cpio.gz)
- name: Run tests in QEMU
run: |
qemu-system-x86_64 \
-device isa-debug-exit,iobase=0xf4,iosize=0x04 \
-kernel linux-${{ env.KERNEL_VERSION }}/arch/x86/boot/bzImage \
-initrd initramfs.cpio.gz \
-drive if=virtio,format=raw,file=disk.img \
-netdev user,id=net0 \
-device e1000,netdev=net0 \
-append "console=ttyS0 rootfstype=ramfs panic=1" \
-nographic -no-reboot -m 1024 -action panic=exit-failure
if [ $? -ne 0 ]; then
echo "tests failed (QEMU exited abnormally)"
exit 1
else
echo "all tests passed"
fi