168 lines
5.0 KiB
Bash
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
|