Files
scoutfs/scripts/check-kernel-compat.sh
2026-03-27 17:03:52 -05:00

168 lines
5.0 KiB
Bash

#!/bin/bash
#
# ScoutFS kernel compatibility check
#
# Standalone script to verify whether scoutfs can build against a given
# set of kernel headers. Used both locally and in CI matrix testing.
#
# Usage: check-kernel-compat.sh [KSRC_PATH]
# Defaults to /lib/modules/$(uname -r)/build
#
# Exit 0 = compatible (build succeeded)
# Exit 1 = incompatible (build failed or headers missing)
#
set -euo pipefail
KSRC="${1:-/lib/modules/$(uname -r)/build}"
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
REPO_ROOT="${SCRIPT_DIR}/.."
# When used in the build repo, the scoutfs source is checked out
# alongside. Allow override via SCOUTFS_SRC env var.
SCOUTFS_SRC="${SCOUTFS_SRC:-${REPO_ROOT}/scoutfs}"
echo "============================================"
echo "ScoutFS Kernel Compatibility Check"
echo "============================================"
echo "Kernel headers: ${KSRC}"
echo "ScoutFS source: ${SCOUTFS_SRC}"
echo ""
# --- Phase 1: Quick header checks ---
echo "--- Phase 1: Header availability ---"
if [ ! -d "$KSRC" ]; then
echo "FAIL: Kernel headers directory not found: ${KSRC}"
exit 1
fi
if [ ! -f "$KSRC/Makefile" ]; then
echo "FAIL: No Makefile in kernel build directory: ${KSRC}"
exit 1
fi
REQUIRED_HEADERS=(
"include/linux/fs.h"
"include/linux/blk_types.h"
"include/linux/bio.h"
"include/linux/net.h"
"include/linux/shrinker.h"
"include/linux/xattr.h"
"include/linux/dcache.h"
"include/linux/posix_acl.h"
"include/linux/slab.h"
"include/linux/rbtree.h"
)
MISSING=0
for header in "${REQUIRED_HEADERS[@]}"; do
if [ -f "${KSRC}/${header}" ]; then
echo " OK: ${header}"
else
echo " MISSING: ${header}"
MISSING=$((MISSING + 1))
fi
done
if [ "$MISSING" -gt 0 ]; then
echo ""
echo "FAIL: ${MISSING} required header(s) missing"
exit 1
fi
echo ""
# --- Phase 2: Kernel version check ---
echo "--- Phase 2: Kernel version ---"
KMAJOR=$(grep '^VERSION' "$KSRC/Makefile" | head -1 | awk '{print $3}')
KMINOR=$(grep '^PATCHLEVEL' "$KSRC/Makefile" | head -1 | awk '{print $3}')
KSUB=$(grep '^SUBLEVEL' "$KSRC/Makefile" | head -1 | awk '{print $3}')
echo " Detected: ${KMAJOR:-?}.${KMINOR:-?}.${KSUB:-?}"
if [ -n "$KMAJOR" ] && [ -n "$KMINOR" ]; then
KVER_NUM=$((KMAJOR * 100 + KMINOR))
if [ "$KVER_NUM" -lt 306 ]; then
echo " FAIL: Kernel too old (minimum 3.6)"
exit 1
fi
echo " OK: Meets minimum version requirement (>= 3.6)"
else
echo " WARNING: Could not determine kernel version, proceeding anyway"
fi
echo ""
# --- Phase 3: Compatibility feature detection ---
echo "--- Phase 3: Compatibility feature detection ---"
COMPAT_MAKEFILE="${SCOUTFS_SRC}/kmod/src/Makefile.kernelcompat"
if [ -f "$COMPAT_MAKEFILE" ]; then
TOTAL=0
DETECTED=0
# Parse the grep-based checks from Makefile.kernelcompat
while IFS= read -r line; do
if [[ "$line" =~ ifneq.*shell\ grep ]]; then
TOTAL=$((TOTAL + 1))
# Extract the pattern and file from the grep command
PATTERN=$(echo "$line" | sed -n "s/.*grep[[:space:]]*'\([^']*\)'.*/\1/p" | head -1)
# Try with -s variant too
if [ -z "$PATTERN" ]; then
PATTERN=$(echo "$line" | sed -n "s/.*grep[[:space:]]*-s[[:space:]]*'\([^']*\)'.*/\1/p" | head -1)
fi
FILE=$(echo "$line" | sed -n 's/.*grep[^)]*[[:space:]]\([a-z].*\))/\1/p' | head -1)
if [ -n "$PATTERN" ] && [ -n "$FILE" ] && [ -f "${KSRC}/${FILE}" ]; then
if grep -q "$PATTERN" "${KSRC}/${FILE}" 2>/dev/null; then
DETECTED=$((DETECTED + 1))
fi
fi
fi
done < "$COMPAT_MAKEFILE"
echo " Compat features detected: ${DETECTED}/${TOTAL}"
echo " (This is informational — both old and new APIs are supported via shims)"
else
echo " WARNING: Makefile.kernelcompat not found at ${COMPAT_MAKEFILE}"
echo " Skipping feature detection (set SCOUTFS_SRC to the scoutfs source directory)"
fi
echo ""
# --- Phase 4: Actual build test ---
echo "--- Phase 4: Build test ---"
if [ ! -d "${SCOUTFS_SRC}/kmod" ]; then
echo " SKIP: ScoutFS kmod source not found at ${SCOUTFS_SRC}/kmod"
echo " (Header checks passed — build likely to succeed)"
echo ""
echo "RESULT: LIKELY COMPATIBLE (build test skipped)"
exit 0
fi
echo " Attempting module build..."
BUILD_LOG=$(mktemp)
if make -C "${SCOUTFS_SRC}/kmod" SK_KSRC="$KSRC" module > "$BUILD_LOG" 2>&1; then
echo " BUILD: SUCCESS"
make -C "${SCOUTFS_SRC}/kmod" SK_KSRC="$KSRC" clean > /dev/null 2>&1 || true
rm -f "$BUILD_LOG"
echo ""
echo "============================================"
echo "RESULT: COMPATIBLE"
echo "============================================"
exit 0
else
echo " BUILD: FAILED"
echo ""
echo " Build log (last 30 lines):"
tail -30 "$BUILD_LOG" | sed 's/^/ /'
rm -f "$BUILD_LOG"
echo ""
echo "============================================"
echo "RESULT: INCOMPATIBLE"
echo "============================================"
exit 1
fi