From a1c33c928a31cd622cc73f2c0db04b925a619451 Mon Sep 17 00:00:00 2001 From: Tomas Srnka Date: Thu, 23 Jul 2026 11:10:22 +0200 Subject: [PATCH 1/3] ci: probe namespace.so runners for the KVM/kernel test requirements Checks everything that blocked or nearly blocked Blacksmith (closed PR 3332): uffd UFFD_FEATURE_WP_ASYNC via a real UFFDIO_API handshake (the actual blocker - needs kernel >= 6.7), nbd driver availability, /dev/kvm, hugepages, cgroup2, swap. Temporary; deleted once the verdict is in. Co-Authored-By: Claude Fable 5 --- .github/workflows/namespace-kernel-probe.yml | 140 +++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 .github/workflows/namespace-kernel-probe.yml diff --git a/.github/workflows/namespace-kernel-probe.yml b/.github/workflows/namespace-kernel-probe.yml new file mode 100644 index 0000000000..88bfcc91e5 --- /dev/null +++ b/.github/workflows/namespace-kernel-probe.yml @@ -0,0 +1,140 @@ +name: Namespace Kernel Probe + +# Temporary diagnostic workflow: establishes whether namespace.so runners can +# host the KVM/kernel-dependent jobs still pinned to GitHub larger runners +# (orchestrator unit shards, integration tests). Checks everything that +# blocked or nearly blocked the Blacksmith attempt (see closed PR #3332): +# - uffd UFFD_FEATURE_WP_ASYNC (Linux >= 6.7) - THE Blacksmith blocker +# - nbd driver availability (module, builtin, or modprobe-able) +# - /dev/kvm (nested virtualization), tun, hugepages, cgroup2, swap +# Delete once the verdict is in. + +on: + pull_request: + paths: + - ".github/workflows/namespace-kernel-probe.yml" + +permissions: + contents: read + +jobs: + probe: + strategy: + fail-fast: false + matrix: + include: + - runner: nscloud-ubuntu-24.04-amd64-8x16 + arch: x64 + - runner: nscloud-ubuntu-24.04-arm64-4x8 + arch: arm64 + runs-on: ${{ matrix.runner }} + timeout-minutes: 15 + steps: + - name: Kernel and device diagnostics + run: | + set -x + uname -a + cat /proc/cmdline || true + echo "--- nbd inventory ---" + ls /dev/nbd* 2>/dev/null | wc -l || true + echo "--- kernel config ---" + CONFIG_SRC="" + [ -e /proc/config.gz ] && CONFIG_SRC=/proc/config.gz + [ -z "$CONFIG_SRC" ] && [ -e "/boot/config-$(uname -r)" ] && CONFIG_SRC="/boot/config-$(uname -r)" + echo "config source: ${CONFIG_SRC:-NONE}" + if [ -n "$CONFIG_SRC" ]; then + zgrep -haE '(MODULES|MODULE_SIG|BLK_DEV_NBD|USERFAULTFD|KVM|HUGETLBFS|SWAP=|TUN|VHOST_VSOCK|PTE_MARKER)' "$CONFIG_SRC" 2>/dev/null | head -20 || true + fi + echo "--- devices / features ---" + ls -la /dev/kvm /dev/net/tun /dev/fuse 2>&1 || true + ls /lib/modules/"$(uname -r)"/ 2>&1 | head -5 || true + cat /sys/fs/cgroup/cgroup.controllers 2>&1 || true + cat /proc/swaps || true + nproc; free -h; df -h / | tail -1 + docker info --format 'docker={{.ServerVersion}} kernel={{.KernelVersion}}' 2>/dev/null || echo "no docker" + + - name: uffd WP_ASYNC feature handshake (the Blacksmith blocker) + run: | + set -euo pipefail + cat > /tmp/uffd_probe.c <<'EOF' + #include + #include + #include + #include + #include + #include + #include + + #ifndef UFFD_FEATURE_WP_ASYNC + #define UFFD_FEATURE_WP_ASYNC (1ULL << 15) + #endif + #ifndef UFFD_FEATURE_WP_UNPOPULATED + #define UFFD_FEATURE_WP_UNPOPULATED (1ULL << 13) + #endif + + int main(void) { + long fd = syscall(__NR_userfaultfd, O_CLOEXEC | O_NONBLOCK); + if (fd < 0) { perror("userfaultfd"); return 2; } + struct uffdio_api api; + memset(&api, 0, sizeof(api)); + api.api = UFFD_API; + if (ioctl(fd, UFFDIO_API, &api) < 0) { perror("UFFDIO_API(features=0)"); return 3; } + printf("supported uffd features: 0x%llx\n", (unsigned long long)api.features); + printf("WP_ASYNC: %s\n", (api.features & UFFD_FEATURE_WP_ASYNC) ? "YES" : "NO"); + printf("WP_UNPOPULATED: %s\n", (api.features & UFFD_FEATURE_WP_UNPOPULATED) ? "YES" : "NO"); + close(fd); + + /* handshake with the exact feature set the orchestrator requests */ + long fd2 = syscall(__NR_userfaultfd, O_CLOEXEC | O_NONBLOCK); + if (fd2 < 0) { perror("userfaultfd(2)"); return 2; } + struct uffdio_api api2; + memset(&api2, 0, sizeof(api2)); + api2.api = UFFD_API; + api2.features = UFFD_FEATURE_WP_ASYNC | UFFD_FEATURE_EVENT_REMOVE | UFFD_FEATURE_MISSING_HUGETLBFS; + if (ioctl(fd2, UFFDIO_API, &api2) < 0) { + perror("UFFDIO_API(orchestrator feature set)"); + return 4; + } + printf("orchestrator feature handshake: OK\n"); + return (api.features & UFFD_FEATURE_WP_ASYNC) ? 0 : 5; + } + EOF + gcc -o /tmp/uffd_probe /tmp/uffd_probe.c + sudo /tmp/uffd_probe + + - name: nbd availability + run: | + set -x + if [ -r /sys/module/nbd/parameters/nbds_max ]; then + echo "nbd driver present (nbds_max=$(cat /sys/module/nbd/parameters/nbds_max))" + elif sudo modprobe nbd nbds_max=256; then + echo "nbd loaded via modprobe" + else + sudo apt-get update -qq && sudo apt-get install -y -qq "linux-modules-extra-$(uname -r)" && sudo modprobe nbd nbds_max=256 + fi + ls /dev/nbd* | wc -l + [ -b /dev/nbd0 ] + + - name: Host feature smoke (hugepages, uffd sysctl, swapfile) + run: | + set -euxo pipefail + echo 1 | sudo tee /proc/sys/vm/unprivileged_userfaultfd + sudo mkdir -p /mnt/hugepages + sudo mount -t hugetlbfs none /mnt/hugepages + echo 256 | sudo tee /proc/sys/vm/nr_hugepages + grep -q . /proc/swaps && [ "$(wc -l < /proc/swaps)" -gt 1 ] && echo "swap already active" || { + sudo fallocate -l 256M /swapfile-probe && sudo chmod 600 /swapfile-probe && sudo mkswap /swapfile-probe && sudo swapon /swapfile-probe && sudo swapoff /swapfile-probe + } + echo "HOST_SMOKE_OK" + + - name: Verdict + run: | + set -x + echo "=== VERDICT for ${{ matrix.runner }} ===" + NBD_OK=false; KVM_OK=false + [ -b /dev/nbd0 ] && NBD_OK=true + [ -e /dev/kvm ] && KVM_OK=true + echo "kernel=$(uname -r) NBD=$NBD_OK KVM=$KVM_OK (WP_ASYNC verdict is the uffd handshake step)" + $NBD_OK + # KVM is required on x64 only (no arm64 runner anywhere has it) + if [ "${{ matrix.arch }}" = "x64" ]; then $KVM_OK; fi From 84cf9dcd91f2b3a4b566cf039f611de4be9bb517 Mon Sep 17 00:00:00 2001 From: Tomas Srnka Date: Thu, 23 Jul 2026 11:13:40 +0200 Subject: [PATCH 2/3] ci: retrigger workflows (initial pull_request event was dropped) From 05ca3cb7d8e42f0dae384932e10d71bd4837fb71 Mon Sep 17 00:00:00 2001 From: Tomas Srnka Date: Thu, 23 Jul 2026 11:32:27 +0200 Subject: [PATCH 3/3] ci: add 22.04 canary label; refire events after app access widened The first two runs queued while the Namespace app did not yet cover this repo - workflow_job events are not re-delivered after access changes, so a fresh push is needed. The 22.04 canary uses the exact label from their docs in case the 24.04 labels are not offered. Co-Authored-By: Claude Fable 5 --- .github/workflows/namespace-kernel-probe.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/namespace-kernel-probe.yml b/.github/workflows/namespace-kernel-probe.yml index 88bfcc91e5..246de27de3 100644 --- a/.github/workflows/namespace-kernel-probe.yml +++ b/.github/workflows/namespace-kernel-probe.yml @@ -27,6 +27,10 @@ jobs: arch: x64 - runner: nscloud-ubuntu-24.04-arm64-4x8 arch: arm64 + # canary: the exact label format from Namespace's docs, in case + # the 24.04 labels above are not offered + - runner: nscloud-ubuntu-22.04-amd64-4x8 + arch: x64 runs-on: ${{ matrix.runner }} timeout-minutes: 15 steps: