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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
| set -euo pipefail
cd "$(dirname "$0")/.."
export PATH="$HOME/.cargo/bin:$PATH:/usr/sbin:/sbin"
for tool in btrfs qemu-system-x86_64 python3; do
command -v $tool >/dev/null || { echo "need $tool (apt install btrfs-progs qemu-system-x86)"; exit 1; }
done
status=0
for img in btrfs btrfs-lzo btrfs-zstd btrfs-convert btrfs-sha256; do
echo "== btrfs check --readonly target/$img.img"
btrfs check --readonly target/$img.img 2>&1 | grep -E "^(found|no error|ERROR)" | sed 's/^/ /' \
|| true
btrfs check --readonly target/$img.img >/dev/null 2>&1 || { echo "!! btrfs check found problems"; status=1; }
done
echo "== run the tests/btrfs.rs kernel"
KERNEL=$(ls -t target/x86_64-rust_kernel/debug/build/rustbelt/*/out/bootimage-btrfs-*.bin 2>/dev/null | head -1 || true)
[ -n "$KERNEL" ] || { echo "no test kernel: run 'cargo test --test btrfs' first"; exit 1; }
LOG=target/btrfs-check.log
drives=()
for img in disk ext2 exfat btrfs ext2-4k ext2-rev0 exfat-512 btrfs-lzo btrfs-zstd btrfs-convert btrfs-sha256; do
drives+=(-drive "file=target/$img.img,format=raw,if=virtio,snapshot=on")
done
set +e
timeout 120 qemu-system-x86_64 -smp 4 -drive format=raw,file="$KERNEL" -no-reboot "${drives[@]}" \
-device isa-debug-exit,iobase=0xf4,iosize=0x04 -serial stdio -display none > $LOG
code=$?
set -e
echo " $(grep -c '\[ok\]' $LOG) btrfs tests ok"
[ $code = 33 ] || { echo "!! test kernel failed (exit $code), see $LOG"; exit 1; }
echo "== compare what Rustbelt read with the host's files (zlib.crc32)"
OUT=$(dirname "$(ls -td target/x86_64-rust_kernel/debug/build/rustbelt/*/out/btrfs-tree | head -1)")
python3 - "$LOG" "$OUT" <<'PY' || status=1
import os, sys, zlib
log, out = sys.argv[1:]
def host(root, skip=()):
"""Every entry under root as the kernel prints it: {path: line}."""
seen = {}
for dirpath, dirs, files in os.walk(root):
for name in dirs + files:
full = os.path.join(dirpath, name)
rel = os.path.relpath(full, root)
if rel.split('/')[0] in skip:
continue
if os.path.islink(full):
seen[rel] = f"L\t{rel}\t{os.readlink(full)}"
elif os.path.isdir(full):
seen[rel] = f"D\t{rel}"
else:
data = open(full, 'rb').read()
seen[rel] = f"F\t{rel}\t{len(data)}\t{zlib.crc32(data):08x}"
return seen
tree, conv = host(f"{out}/btrfs-tree"), host(f"{out}/btrfs-convert-tree")
want = {"/mnt/disk3": tree, "/mnt/disk7": tree, "/mnt/disk8": tree, "/mnt/disk9": conv}
got = {m: {} for m in want}
for line in open(log, errors='replace'):
if "[btrfs-file] " in line: # (the first may follow the test's name)
mount, rest = line.split("[btrfs-file] ", 1)[1].rstrip('\n').split('\t', 1)
got[mount][rest.split('\t')[1]] = rest
total_bad = 0
for mount, files in want.items():
bad = 0
# Only on the converted disk: made by mke2fs / btrfs-convert, not in the tree.
extra = {p for p in got[mount] if p in ("lost+found", "ext2_saved") or p.startswith("ext2_saved/")}
for p in sorted(set(files) | set(got[mount]) - extra):
if files.get(p) != got[mount].get(p):
print(f" !! {mount} {p}: host {files.get(p)!r}, Rustbelt {got[mount].get(p)!r}"); bad += 1
n = sum(1 for l in files.values() if l[0] == 'F')
size = sum(int(l.split('\t')[2]) for l in files.values() if l[0] == 'F')
print(f" {mount}: {len(files)} entries ({n} files, {size} bytes) {'match' if not bad else 'DIFFER'}")
total_bad += bad
sys.exit(1 if total_bad else 0)
PY
[ $status = 0 ] && echo "== all good" || echo "== problems found"
exit $status
|