update
This commit is contained in:
Executable
+190
@@ -0,0 +1,190 @@
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
: "${PRE15_DUT:?PRE15_DUT is required}"
|
||||
: "${PRE15_ROOT:?PRE15_ROOT is required}"
|
||||
: "${PRE15_RUN_DIR:?PRE15_RUN_DIR is required}"
|
||||
: "${PRE15_LIB_DIR:?PRE15_LIB_DIR is required}"
|
||||
. "$PRE15_LIB_DIR/runner.sh"
|
||||
|
||||
internal=$PRE15_DUT/src/internal.h
|
||||
data=$PRE15_DUT/src/data.c
|
||||
inode=$PRE15_DUT/src/inode.c
|
||||
super=$PRE15_DUT/src/super.c
|
||||
zmap=$PRE15_DUT/src/zmap.c
|
||||
linux_internal=$PRE15_ROOT/src-linux/internal.h
|
||||
artifacts=$PRE15_RUN_DIR/artifacts
|
||||
|
||||
for tool in python3 sha256sum; do
|
||||
command -v "$tool" >/dev/null 2>&1 || \
|
||||
pre15_infra_blocked "missing B05 host tool: $tool"
|
||||
done
|
||||
|
||||
pre15_record_fixture b05-freebsd-internal "$internal"
|
||||
pre15_record_fixture b05-freebsd-data "$data"
|
||||
pre15_record_fixture b05-freebsd-inode "$inode"
|
||||
pre15_record_fixture b05-freebsd-super "$super"
|
||||
pre15_record_fixture b05-freebsd-zmap "$zmap"
|
||||
pre15_record_fixture b05-linux-internal "$linux_internal"
|
||||
|
||||
mkdir -p "$artifacts"
|
||||
pre15_target_reached
|
||||
|
||||
if python3 - "$PRE15_ROOT" "$artifacts/field-check.json" <<'PY'
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
from pathlib import Path
|
||||
import re
|
||||
import sys
|
||||
|
||||
|
||||
root = Path(sys.argv[1])
|
||||
output = Path(sys.argv[2])
|
||||
dut_src = root / "repo-pre-15" / "src"
|
||||
internal = (dut_src / "internal.h").read_text(encoding="utf-8")
|
||||
data = (dut_src / "data.c").read_text(encoding="utf-8")
|
||||
inode = (dut_src / "inode.c").read_text(encoding="utf-8")
|
||||
super_source = (dut_src / "super.c").read_text(encoding="utf-8")
|
||||
zmap = (dut_src / "zmap.c").read_text(encoding="utf-8")
|
||||
linux = (root / "src-linux" / "internal.h").read_text(encoding="utf-8")
|
||||
|
||||
|
||||
def struct_body(source: str, name: str) -> str:
|
||||
match = re.search(
|
||||
rf"^struct {re.escape(name)} \{{\n(?P<body>.*?)^\}};",
|
||||
source,
|
||||
re.MULTILINE | re.DOTALL,
|
||||
)
|
||||
if not match:
|
||||
raise SystemExit(f"missing struct {name}")
|
||||
return match.group("body")
|
||||
|
||||
|
||||
def fields(source: str, name: str) -> list[str]:
|
||||
result = []
|
||||
for line in struct_body(source, name).splitlines():
|
||||
declaration = line.strip()
|
||||
if not declaration or declaration.startswith("/*"):
|
||||
continue
|
||||
match = re.search(r"([A-Za-z_][A-Za-z0-9_]*)\s*(?:\[[^]]+\])?;$", declaration)
|
||||
if not match:
|
||||
raise SystemExit(f"unparsed field in struct {name}: {declaration!r}")
|
||||
result.append(match.group(1))
|
||||
return result
|
||||
|
||||
|
||||
freebsd_device = fields(internal, "erofs_device_info")
|
||||
linux_device = fields(linux, "erofs_device_info")
|
||||
expected_device = [
|
||||
"devvp",
|
||||
"dev",
|
||||
"cp",
|
||||
"mediasize",
|
||||
"sectorsize",
|
||||
"blocks",
|
||||
"uniaddr",
|
||||
]
|
||||
if freebsd_device != expected_device:
|
||||
raise SystemExit(f"FreeBSD device field order mismatch: {freebsd_device!r}")
|
||||
if [field for field in linux_device if field in {"blocks", "uniaddr"}] != [
|
||||
"blocks",
|
||||
"uniaddr",
|
||||
]:
|
||||
raise SystemExit(f"Linux device common-field order mismatch: {linux_device!r}")
|
||||
|
||||
freebsd_map = fields(internal, "erofs_map_dev")
|
||||
linux_map = fields(linux, "erofs_map_dev")
|
||||
expected_map = ["m_dif", "m_pa", "m_deviceid", "m_plen"]
|
||||
if freebsd_map != expected_map:
|
||||
raise SystemExit(f"FreeBSD map field order mismatch: {freebsd_map!r}")
|
||||
if [field for field in linux_map if field in {"m_dif", "m_pa", "m_deviceid"}] != [
|
||||
"m_dif",
|
||||
"m_pa",
|
||||
"m_deviceid",
|
||||
]:
|
||||
raise SystemExit(f"Linux map common-field order mismatch: {linux_map!r}")
|
||||
|
||||
inode_fields = fields(internal, "erofs_inode")
|
||||
for removed in ("ino", "inline_data"):
|
||||
if removed in inode_fields:
|
||||
raise SystemExit(f"removed inode field remains: {removed}")
|
||||
if "m_sbi" in freebsd_map:
|
||||
raise SystemExit("removed map back-pointer remains")
|
||||
|
||||
removed_uses = {
|
||||
"map back-pointer": sum(
|
||||
source.count("m_sbi") for source in (internal, data, inode, super_source, zmap)
|
||||
),
|
||||
"saved ondisk ino": len(re.findall(r"\bvi->ino\b", inode)),
|
||||
"inline-data cache": len(re.findall(r"\bvi->inline_data\b", inode)),
|
||||
}
|
||||
if any(removed_uses.values()):
|
||||
raise SystemExit(f"removed field use remains: {removed_uses!r}")
|
||||
|
||||
helper = re.search(
|
||||
r"erofs_fill_from_devinfo\(struct erofs_map_dev \*map,\n"
|
||||
r" struct erofs_device_info \*dif, erofs_off_t pa\)",
|
||||
data,
|
||||
)
|
||||
if not helper:
|
||||
raise SystemExit("map helper still accepts the removed super back-pointer")
|
||||
if len(re.findall(r"erofs_fill_from_devinfo\(", data)) != 4:
|
||||
raise SystemExit("unexpected map helper definition/call count")
|
||||
|
||||
initializer = re.search(
|
||||
r"map = \(struct erofs_map_dev\) \{\n"
|
||||
r"\t\t\.m_pa = off,\n"
|
||||
r"\t\t\.m_deviceid = device_id,\n"
|
||||
r"\t\t\.m_plen = len,\n"
|
||||
r"\t\};",
|
||||
data,
|
||||
)
|
||||
if not initializer:
|
||||
raise SystemExit("erofs_map_dev initializer order mismatch")
|
||||
|
||||
required_markers = {
|
||||
"raw nid identity": "vi->nid = nid;",
|
||||
"layout source": "vi->datalayout = erofs_inode_datalayout(ifmt);",
|
||||
"device vnode": "struct vnode *devvp;",
|
||||
"GEOM consumer": "struct g_consumer *cp;",
|
||||
"provider media size": "uint64_t mediasize;",
|
||||
"provider sector size": "uint32_t sectorsize;",
|
||||
"future volume label": "char volume_name[17];",
|
||||
"deferred LZ4 state": "struct erofs_sb_lz4_info lz4;",
|
||||
}
|
||||
for label, marker in required_markers.items():
|
||||
if marker not in internal and marker not in inode:
|
||||
raise SystemExit(f"required ownership/source marker missing: {label}")
|
||||
|
||||
result = {
|
||||
"freebsd_device_fields": freebsd_device,
|
||||
"freebsd_map_fields": freebsd_map,
|
||||
"linux_device_common_fields": [
|
||||
field for field in linux_device if field in {"blocks", "uniaddr"}
|
||||
],
|
||||
"linux_map_common_fields": [
|
||||
field for field in linux_map if field in {"m_dif", "m_pa", "m_deviceid"}
|
||||
],
|
||||
"removed_field_uses": removed_uses,
|
||||
"retained_freebsd_ownership_fields": [
|
||||
"devvp",
|
||||
"dev",
|
||||
"cp",
|
||||
"mediasize",
|
||||
"sectorsize",
|
||||
],
|
||||
}
|
||||
with output.open("x", encoding="ascii") as stream:
|
||||
json.dump(result, stream, ensure_ascii=True, indent=2, sort_keys=True)
|
||||
stream.write("\n")
|
||||
print("fields PASS device=7 map=4 removed-uses=0")
|
||||
PY
|
||||
then
|
||||
:
|
||||
else
|
||||
pre15_dut_fail 'B05 field layout or write-only closure oracle failed'
|
||||
fi
|
||||
|
||||
sha256sum "$artifacts/field-check.json" > "$artifacts/SHA256SUMS"
|
||||
printf 'B05 PASS private field model and zero-consumer closure\n'
|
||||
Reference in New Issue
Block a user