Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,15 @@ This project automates the building of custom Linux kernels for Firecracker micr
# or directly
./build.sh
```
The built kernels will be placed in `builds/vmlinux-<version>/vmlinux.bin`.
The built kernels will be placed in `builds/vmlinux-<version>/<arch>/vmlinux.bin` where `<arch>` is `amd64` or `arm64` (Go/OCI convention). For x86_64 backward compatibility, a legacy copy is also placed at `builds/vmlinux-<version>/vmlinux.bin`.

## Development Workflow
- On every push, GitHub Actions will automatically build the kernels and save it as an artifact.

## Architecture naming

Output directories use Go's `runtime.GOARCH` convention (`amd64`, `arm64`) so they match the infra orchestrator's `TargetArch()` path resolution. The build-time variable `TARGET_ARCH` (`x86_64`, `arm64`) is only used internally for config paths and cross-compilation flags.

## New Kernel in E2B's infra
_Note: these steps should give you new kernel on your self-hosted E2B using https://github.com/e2b-dev/infra_

Expand Down
22 changes: 17 additions & 5 deletions build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,18 @@ set -euo pipefail
TARGET_ARCH="${TARGET_ARCH:-x86_64}"
HOST_ARCH="$(uname -m)"

# Go/OCI-normalized arch name for output directory structure.
# The infra orchestrator uses Go's runtime.GOARCH convention (amd64/arm64)
# for path resolution, so output directories must match.
normalize_arch() {
case "$1" in
x86_64) echo "amd64" ;;
aarch64) echo "arm64" ;;
*) echo "$1" ;;
esac
}
OUTPUT_ARCH="$(normalize_arch "$TARGET_ARCH")"

function install_dependencies {
local packages=(
bc bison busybox-static cpio curl flex gcc libelf-dev libssl-dev make patch squashfs-tools tree
Expand Down Expand Up @@ -59,14 +71,14 @@ function build_version {
fi

echo "Copying finished build to builds directory"
# Always output to {arch}/ subdirectory
mkdir -p "../builds/vmlinux-${version}/${TARGET_ARCH}"
# Output to normalized arch dir (amd64/arm64) matching Go's runtime.GOARCH
mkdir -p "../builds/vmlinux-${version}/${OUTPUT_ARCH}"
if [[ "$TARGET_ARCH" == "arm64" ]]; then
cp arch/arm64/boot/Image "../builds/vmlinux-${version}/${TARGET_ARCH}/vmlinux.bin"
cp arch/arm64/boot/Image "../builds/vmlinux-${version}/${OUTPUT_ARCH}/vmlinux.bin"
else
cp vmlinux "../builds/vmlinux-${version}/${TARGET_ARCH}/vmlinux.bin"
cp vmlinux "../builds/vmlinux-${version}/${OUTPUT_ARCH}/vmlinux.bin"
fi

# x86_64: also copy to legacy path (no arch subdir) for backwards compat
if [[ "$TARGET_ARCH" == "x86_64" ]]; then
cp vmlinux "../builds/vmlinux-${version}/vmlinux.bin"
Expand Down
94 changes: 94 additions & 0 deletions migrate-gcs-arch.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
#!/bin/bash
# Copies kernel files from x86_64/ to amd64/ subdirectories in GCS buckets.
#
# The infra orchestrator's TargetArch() normalizes x86_64 -> amd64 (Go convention),
# so kernels stored under x86_64/ are never found by the arch-aware path resolution,
# causing a gcsfuse stat penalty on every sandbox create.
#
# Usage:
# ./migrate-gcs-arch.sh <bucket> # dry-run: show what would be copied
# ./migrate-gcs-arch.sh <bucket> --apply # copy x86_64/ -> amd64/
# ./migrate-gcs-arch.sh <bucket> --delete-old # dry-run: show what old x86_64/ files would be deleted
# ./migrate-gcs-arch.sh <bucket> --delete-old --apply # actually delete old x86_64/ files
#
# Recommended workflow:
# 1. ./migrate-gcs-arch.sh gs://my-bucket # review what will be copied
# 2. ./migrate-gcs-arch.sh gs://my-bucket --apply # copy to amd64/
# 3. ... verify everything works ...
# 4. ./migrate-gcs-arch.sh gs://my-bucket --delete-old # review what will be deleted
# 5. ./migrate-gcs-arch.sh gs://my-bucket --delete-old --apply # clean up old x86_64/

set -euo pipefail

BUCKET="${1:?Usage: $0 <bucket> [--apply] [--delete-old]}"
shift

APPLY=false
DELETE_OLD=false
for arg in "$@"; do
case "$arg" in
--apply) APPLY=true ;;
--delete-old) DELETE_OLD=true ;;
*) echo "Unknown flag: $arg"; exit 1 ;;
esac
done

# Normalize bucket name — strip gs:// prefix if provided, we add it back
BUCKET="${BUCKET#gs://}"

echo "Scanning gs://${BUCKET} for x86_64/ paths..."
echo ""

objects=$(gsutil ls -r "gs://${BUCKET}/**/x86_64/**" 2>/dev/null || true)

if [[ -z "$objects" ]]; then
echo "No x86_64/ paths found in gs://${BUCKET}"
exit 0
fi

count=0
if [[ "$DELETE_OLD" == true ]]; then
while IFS= read -r src; do
[[ -z "$src" ]] && continue
[[ "$src" == */ ]] && continue

if [[ "$APPLY" == true ]]; then
echo " DELETE $src"
gsutil rm "$src"
else
echo " [dry-run] would delete $src"
fi
((count++)) || true
done <<< "$objects"

echo ""
echo "Total: $count objects"
if [[ "$APPLY" != true ]]; then
echo ""
echo "This was a dry run. Add --apply to actually delete."
fi
else
while IFS= read -r src; do
[[ -z "$src" ]] && continue
[[ "$src" == */ ]] && continue

dst="${src/\/x86_64\///amd64/}"

if [[ "$APPLY" == true ]]; then
echo " COPY $src"
echo " -> $dst"
gsutil cp "$src" "$dst"
else
echo " [dry-run] $src"
echo " -> $dst"
fi
((count++)) || true
done <<< "$objects"

echo ""
echo "Total: $count objects"
if [[ "$APPLY" != true ]]; then
echo ""
echo "This was a dry run. Add --apply to actually copy."
fi
fi
Loading