wip(blocks): a BAM flush reads and writes only the pages that hold the volume's bits (#155) [skip ci]
Not yet accepted. bam_flush_to_disk() and bam_sync_from_disk() read and wrote every page of the BAM; with the stick's BAM sized for 256 GiB (6144 devblocks, 24 MiB) every flush of a dirty block moved 24 MiB each way. They now touch only the pages that hold the slot's bits -- its reserved bits and one per user block (bam_pages_used()) -- the pages past them are never set, so the bytes on disk are the same. Test (qemu_session.py bam_flush, --target qemu-stick --stick-gib 16): three SAVE-BUFFERS of an Artemis block, each timed, then the BAM hashed. Before: 5.1 / 5.6 / 6.1 s (the 2 s limit fails; it was set after seeing this baseline). After: 1.1 / 1.1 / 1.1 s. The BAM's bytes the same either way: sha256 79197a40...b9e44b50, 5 non-zero bytes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
This commit is contained in:
+38
-2
@@ -63,6 +63,9 @@ the stick's, plan 2026-10-26-stick-1-screen-and-keyboard.md):
|
||||
on the copy is clean (plan 2026-10-29-stick-5, Task 2)
|
||||
stick_small --target qemu-stick --stick-gib 4: under 8 GB -- not grown, said so; Artemis at the
|
||||
image's size; the prompt
|
||||
bam_flush --target qemu-stick --stick-gib 16: an Artemis block changed and SAVE-BUFFERS'd three
|
||||
times, each timed (TIME:); each answers ok within 2 s (#155: it took 5-6 s); then the BAM's bytes on the
|
||||
stick hashed (BAM:), to be the same before and after #155's change
|
||||
stick_artemis ARTDISK= (no virtio disk): Artemis and Zuse from the Zuse stick alone -- the
|
||||
stick's Artemis partition attached first (785938 user blocks), then its identity
|
||||
(48724); [zuse@Hera] ok> (plan 2026-10-27-stick-4-one-disk.md, Task 4)
|
||||
@@ -106,7 +109,7 @@ NO_ZUSE_MODES = {"gpt_zuse", "gpt_hotplug", "gpt_foreign", "gpt_bad_crc", "gpt_b
|
||||
"alttab_after_logout", "alttab_before_pull", "emergency_pull",
|
||||
"screen_dark_until_login", "screen_console_after_login", "screen_dark_after_logout",
|
||||
"kbd_typeahead", "stick_boot", "stick_v3", "stick_zuse", "screen_boot", "genesis",
|
||||
"stick_genesis", "stick_grow", "stick_small"}
|
||||
"stick_genesis", "stick_grow", "stick_small", "bam_flush"}
|
||||
label = a.label or f"{a.mode}-{a.arch}"
|
||||
work = os.path.join(ROOT, "build", "qemu-session", label)
|
||||
shutil.rmtree(work, ignore_errors=True)
|
||||
@@ -156,7 +159,7 @@ if a.mode == "stick_zuse":
|
||||
make_args.append(f"STICK_PAIR={work}") # the PC stick with this session's copy of the pair
|
||||
if a.stick_gib:
|
||||
make_args.append(f"STICK_GIB={a.stick_gib}")
|
||||
if a.mode in ("stick_grow", "stick_small"):
|
||||
if a.mode in ("stick_grow", "stick_small", "bam_flush"):
|
||||
make_args.append("KERNEL_ARGS=--log-level=info") # the blk: disk lines the sizes are read from
|
||||
if a.mode == "genesis":
|
||||
# a fresh data stick, made once into this session's directory and booted twice: the second
|
||||
@@ -531,6 +534,39 @@ elif m in ("stick_grow", "stick_small"):
|
||||
v.returncode == 0 and "No errors detected" in v.stdout + v.stderr)
|
||||
boot_done = True
|
||||
|
||||
elif m == "bam_flush":
|
||||
check("[zuse@Hera] ok>", wait_for(PROMPT, 600))
|
||||
lbns = re.findall(r"blk: disk .*? LBN (\d+)\.\.(\d+)", text())
|
||||
check(f"Artemis's LBN range ({lbns[:1]})", bool(lbns))
|
||||
first = int(lbns[0][0]) if lbns else 0
|
||||
times = []
|
||||
for i in range(3):
|
||||
blk = first + 100 + i
|
||||
n = count(PROMPT)
|
||||
type_line(f"{blk} BLOCK DROP UPDATE")
|
||||
check(f"block {blk} changed", wait_for(PROMPT, 60, n))
|
||||
n = count(PROMPT)
|
||||
t = time.time()
|
||||
type_line("SAVE-BUFFERS")
|
||||
done = wait_for(PROMPT, 300, n)
|
||||
times.append(time.time() - t)
|
||||
print(f"TIME: SAVE-BUFFERS of block {blk}: {times[-1]:.1f} s", flush=True)
|
||||
check(f"SAVE-BUFFERS answers ok within 2 s ({times[-1]:.1f} s)", done and times[-1] < 2)
|
||||
check("no fault", count(r"EXCEPTION|PANIC|panic") == 0)
|
||||
shutdown()
|
||||
boot_done = True
|
||||
sf = shutil.which("sfdisk") or "/usr/sbin/sfdisk"
|
||||
run = os.path.join(ROOT, "build", a.arch, "kernel", "stick-run.img")
|
||||
parts = json.loads(subprocess.run([sf, "--json", run], capture_output=True, text=True).stdout)
|
||||
art = [q for q in parts["partitiontable"]["partitions"]
|
||||
if q["type"].upper() == "BCD7B586-1C8E-4EEF-86A3-273A8D8EE624"][0]
|
||||
import hashlib
|
||||
with open(run, "rb") as f:
|
||||
f.seek(art["start"] * 512 + 4096) # the BAM: devblocks 1 .. 6144 of Artemis
|
||||
bam = f.read(6144 * 4096)
|
||||
print(f"BAM: sha256 {hashlib.sha256(bam).hexdigest()}, {sum(1 for x in bam if x)} non-zero bytes",
|
||||
flush=True)
|
||||
|
||||
elif m == "stick_v3":
|
||||
t = text()
|
||||
check("Boot disk: a StarshipOS stick", re.search(r"Boot disk: a StarshipOS stick", t) is not None)
|
||||
|
||||
Reference in New Issue
Block a user