RustForge

rust-kernel

Rustbelt: a hobby x86_64 kernel written in Rust

rust-kernel / scripts / ext2-check.sh
3344 bytes ยท raw
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#!/usr/bin/env bash
# Check Rustbelt's ext2 writes with the host's own tools (e2fsprogs).
#
#   1. e2fsck the pristine images build.rs made (sanity check of the build).
#   2. Copy them to target/fsck/ and boot Rustbelt on the *writable* copies
#      (no snapshot=on), so whatever it writes really lands in the files:
#        - the shell self-test (cp B: -> C:, mkdir, echo > file)
#        - the tests/ext2.rs kernel (create/write/truncate/unlink/rmdir on
#          all three images: 1 KiB blocks, 4 KiB blocks, revision 0)
#   3. `e2fsck -fn` every copy: -f = check even if marked clean, -n = open
#      read-only and answer "no" to every question (report, don't fix).
#      Any complaint means the driver wrote something inconsistent.
#   4. Show the root directory with debugfs, to see the new files.
#
# Usage: ./scripts/ext2-check.sh   (after `cargo build` and
#        `cargo test --test ext2`, which build the images and the kernels)
set -euo pipefail
cd "$(dirname "$0")/.."
T="${CARGO_TARGET_DIR:-target}" # stage 21: the build output (cargo's target dir)
export PATH="$HOME/.cargo/bin:$PATH:/usr/sbin:/sbin"
for tool in e2fsck debugfs qemu-system-x86_64; do
    command -v $tool >/dev/null || { echo "need $tool (apt install e2fsprogs qemu-system-x86)"; exit 1; }
done

fsck() { # fsck <image> <title>
    echo "== e2fsck -fn $1 ($2)"
    e2fsck -fn "$1" || { echo "!! e2fsck found problems in $1"; status=1; }
}
status=0

for img in $T/ext2.img $T/ext2-4k.img $T/ext2-rev0.img; do
    fsck $img "pristine, as built"
done

mkdir -p $T/fsck
cp $T/ext2.img $T/fsck/selftest.img
for img in ext2 ext2-4k ext2-rev0; do cp $T/$img.img $T/fsck/tests-$img.img; done

echo "== boot the shell self-test on $T/fsck/selftest.img"
EXT2_IMG=$T/fsck/selftest.img ./scripts/run-headless.sh >/dev/null && echo "self-test OK"

echo "== run the tests/ext2.rs kernel on $T/fsck/tests-*.img"
KERNEL=$(ls -t $T/x86_64-rust_kernel/debug/build/rustbelt/*/out/bootimage-ext2-*.bin 2>/dev/null | head -1 || true)
[ -n "$KERNEL" ] || { echo "no test kernel: run 'cargo test --test ext2' first"; exit 1; }
set +e
timeout 120 qemu-system-x86_64 -smp 4 -drive format=raw,file="$KERNEL" -no-reboot \
    -drive file=$T/disk.img,format=raw,if=virtio,snapshot=on \
    -drive file=$T/fsck/tests-ext2.img,format=raw,if=virtio \
    -drive file=$T/exfat.img,format=raw,if=virtio,snapshot=on \
    -drive file=$T/btrfs.img,format=raw,if=virtio,snapshot=on \
    -drive file=$T/fsck/tests-ext2-4k.img,format=raw,if=virtio \
    -drive file=$T/fsck/tests-ext2-rev0.img,format=raw,if=virtio \
    -drive file=$T/exfat-512.img,format=raw,if=virtio,snapshot=on \
    -device isa-debug-exit,iobase=0xf4,iosize=0x04 \
    -serial stdio -display none > $T/fsck/tests.log
code=$?
set -e
grep -c "\[ok\]" $T/fsck/tests.log | sed 's/$/ ext2 tests ok/'
[ $code = 33 ] || { echo "!! test kernel failed (exit $code), see $T/fsck/tests.log"; exit 1; }

for img in $T/fsck/selftest.img $T/fsck/tests-ext2*.img; do
    fsck "$img" "after Rustbelt wrote to it"
done

echo "== debugfs: ls -l / on the self-test copy"
debugfs -R "ls -l /" $T/fsck/selftest.img 2>/dev/null
echo "== debugfs: cat /made-here/note.txt"
debugfs -R "cat /made-here/note.txt" $T/fsck/selftest.img 2>/dev/null

[ $status = 0 ] && echo "== all images are clean" || echo "== e2fsck found problems"
exit $status