Skip to content

Fail flash backup on data or checksum write errors - #85

Open
markmounteer wants to merge 2 commits into
LinuxCNC:masterfrom
markmounteer:fix/w4-mesaflash-backup-io-deepseek-20261025
Open

markmounteer wants to merge 2 commits into
LinuxCNC:masterfrom
markmounteer:fix/w4-mesaflash-backup-io-deepseek-20261025

Conversation

@markmounteer

Copy link
Copy Markdown

Fail flash backup on data or checksum write errors

Stacked on draft PR84 (2c6a2f46ec4ffd2be0dc63a28f8cc34fe730179f), whose Efinix reload-payload repair is preserved unchanged. This PR adds one commit on top; review the top commit for this change.

Defect

flash_backup in eeprom.c ignored the results of the data-file fwrite and fclose and of the checksum-file fprintf and fclose, then printed success and returned 0. The SHA256 was updated from the incoming page buffers whether or not the bytes were saved, so the .sha256 sidecar could describe a complete image that was never successfully written. A failed or partial backup could therefore look like a trustworthy recovery artifact.

Fix (only flash_backup in eeprom.c)

  1. Every page fwrite must return PAGE_SIZE. On a short or zero write, reading stops immediately (no further page reads), the partial data file is removed, no checksum is created, no success is announced, and -1 is returned.
  2. SHA256_Update runs only after that page was fully written, so the sidecar can only describe saved bytes.
  3. A failing data-file fclose (delayed flush error) removes the data file and returns -1 with no checksum and no success message.
  4. Checksum failures are checked too: fprintf and fclose failures (and the existing fopen failure) remove the sidecar and the data file and return -1.
  5. Success messages print only after the data file is fully written and closed and the sidecar is fully written and closed.

Partial-file policy, documented in a comment above the function: a backup is successful only when both files are fully written and closed; on any failure both artifacts are removed best-effort so no partial artifact can be mistaken for a completed backup. The -1 result reaches the process exit status because mesaflash.c assigns the anyio_dev_backup_flash result to ret and returns it from main (that propagation already existed and is unchanged).

No EEPROM programming, erase or header logic, short-final-page programming semantics, reload behavior, global build options, or the shared Makefile were changed.

Tests (new files only)

tests/test_flash_backup.c links the real eeprom.c with a deterministic memory-backed read_page stub and GNU ld --wrap injection for fopen/fwrite/fclose/fprintf. No physical transport is linked or called. Run it with the dedicated makefile (the shared Makefile is untouched):

make -f tests/Makefile.test-backup check

Seven bounded cases: exact-length success with verified bytes and sidecar digest, short first-page write, zero first-page write, later-page (10th) write failure, delayed data-close failure, checksum-write failure, and checksum-close failure. Failure cases assert return -1 (the caller-visible failure), stopped reads where applicable, and that neither artifact remains.

Validation (Azure ARM64, vm-cnc-build3-cc, GCC 13.3.0, Ubuntu 24.04)

  • Baseline 2c6a2f46 plus the identical new fixture: 7 cases, 21 failed assertions. The success case passes; all six failure cases return 0, keep reading, leave both files, and publish the same sidecar digest as the success case.
  • Fixed exact-commit archive: full make build passes with -Wall -Wextra -Werror; backup regression 7 cases, 0 failed assertions; existing reload regression (make check) 50 cases, 0 failed assertions.
  • New ARM64 mesaflash binary from the exact-commit build: SHA256 6ebc9111ca4fffa0900cbfa1ed23099675252d73988fdb1444501e0153e2f127. It needs a new source/binary pin before any installation use.

No board, Pi, flashing, reload, deployment, or merge was performed. This proves backup failure handling in software only; it proves no current backup or physical recovery.

flash_backup ignored fwrite, fclose and fprintf results, hashed pages whether or not they were saved, printed success and returned 0. A backup now succeeds only when the data file is fully written and closed and the sha256 sidecar is fully written and closed. On any failure reading stops, the data file and any sidecar are removed so no partial artifact looks complete, and -1 reaches the CLI exit status. Adds an offline regression with memory-backed page reads and ld --wrap stdio failure injection.
@markmounteer
markmounteer marked this pull request as ready for review October 28, 2026 02:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant