Repository navigation
A commit whose committed-slot record cannot be written is a failed commit: the trial stays, and the next boot commits again - #258
Merged
Conversation
…are renamed into place, and boot-success writes no record nothing reads On FAT only the rename is not atomic, so the kernels, BOOTX64.EFI and kryptik-recover's records are written to a new name, fsynced, then renamed. boot-success's committed-slot and kryptik-update's version-a/b skipped the fsync: a power cut after the rename could leave the record with a cluster that was never written, which the readers show as unknown and an apply then refuses as naming no committed slot. Both now fsync first. boot-success also copied version-X to version-committed on every commit. Nothing reads it, and kryptik-recover --commit-slot never updated it, so it could name the wrong release; it is no longer written.
…ed copy: the version and committed-slot records are written as the kernels are It named two renames as the only non-atomic steps, and the version file and committed-slot were renamed without an fsync before them.
…mmit: the trial stays, and the next boot commits again boot-success's commit_slot returned 0 once BOOTX64.EFI was the slot's kernel, whatever became of the committed-slot record. With the record unwritten, the caller cleared the trial, recorded "commit b", forgot the entries and raised the clock's floor while the ESP still named a: the next boot found b running uncommitted and rebooted once for nothing, and kryptik-update refused every apply from b until kryptik-recover --commit-slot b from the medium. Now the record is part of the commit. Failing it keeps the trial, and since BOOTX64.EFI already boots b and kryptik-efiboot's entries come after it in BootOrder, the next boot finds BOOTX64.EFI already b and writes only the record. kryptik-recover's put already dies the same way. kryptik-update says which ESP write failed when the staged kernel's flush or the version record fails, instead of leaving set -e to exit without a word.
…slot: a boot file that could not be replaced left the ESP naming a slot the firmware does not boot From a non-author read: when the copy, flush or rename of BOOTX64.EFI failed, commit_slot still rewrote committed-slot to the trial's slot. The next boot took BOOTX64.EFI, the old slot, whose applies kryptik-update then refused as not committed. The fixture fails that step and expects the record unchanged.
DevomB
marked this pull request as ready for review
October 9, 2026 03:58
This was referenced Oct 9, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follows #251 (esp-records-fsync, now on main); this PR's changes are e7ae447 and c346847.
What was wrong (found by 4e's non-author read of #251; it predates #251).
commit_slotin boot-success returned 0 onceBOOTX64.EFIwas the slot's kernel, whatever became of thecommitted-slotrecord after it. If that record could not be written, the caller still:commit b,while the ESP still named slot a. On the next boot, boot-success found b running uncommitted and rebooted once for nothing. From then on
kryptik-update apply(since #238) refused every apply from b untilkryptik-recover --commit-slot bwas run from the medium.And the other way round (4e's second read). When the copy, flush or rename of
BOOTX64.EFIfailed,commit_slotstill rewrotecommitted-slotto the trial's slot. The next boot tookBOOTX64.EFI, which is the old slot, andkryptik-updaterefused applies from it because the ESP named another slot as committed.What changed.
build/service-scripts/boot-success.sh: the record is part of the commit, and is written only onceBOOTX64.EFIboots the slot. Failing to write it sets rc=1, the trial stays andcommit-failed bis recorded.kryptik-efibootappends its entries after the disk's ownBOOTX64.EFIin BootOrder, and that file already boots b. So the next boot judges the same trial, findsBOOTX64.EFIalready b, and writes only the record. The caller's message no longer claims "the committed slot is unchanged", which a failed record write makes untrue. It says the trial stays.kryptik-recover'sputalready dies on the same failure.tools/update/kryptik-update: the staged kernel's flush and the version record's write say which failed, instead of exiting throughset -ewithout a message (4e's INFO).tools/tests/boot-success.sh: thesyncstand-in can fail forcommitted-slot.new. One new case checks that the commit then fails, the record still names a, the trial is kept and no entries are forgotten. A second fails theBOOTX64.EFIflush and expects the old boot file, the record still naming a, and the trial kept.How the run proves it. CI's fixture step runs the new case. Distro run 37877029582 boots through commits and applies in the update, install and integrity suites.