Skip to content

Write config files through a temp file and rename (nRF52, STM32) - #3763

Open
marcelverdult wants to merge 1 commit into
meshcore-dev:devfrom
marcelverdult:upstream-candidate/atomic-fs-writes
Open

marcelverdult wants to merge 1 commit into
meshcore-dev:devfrom
marcelverdult:upstream-candidate/atomic-fs-writes

Conversation

@marcelverdult

Copy link
Copy Markdown
Contributor

Problem

Identity, prefs, contacts, channels, ACL and regions are saved with remove(file) followed by open(FILE_O_WRITE) and a rewrite. If power drops between the remove and the end of the rewrite, the file is gone or short. On a node that runs a battery flat this loses the identity or the contact list.

Change

New AtomicFile::write(). On littlefs platforms (nRF52, STM32) it writes <file>.tmp, closes it, checks that the size on flash matches what was written, and renames it over the target. lfs_rename() replaces an existing target in one commit, so a power loss leaves the old or the new file. Orphaned .tmp files are removed when the file is loaded.

Used by IdentityStore, CommonCLI prefs, ClientACL, RegionMap and the companion DataStore (prefs, contacts, channels).

  • If the temp copy does not fit, or the write or rename fails, it falls back to the old in-place behaviour. Without that, a board with a small internal filesystem could stop saving a large contact list.
  • ESP32 and RP2040 are unchanged. Define MESH_ATOMIC_FS_WRITES to switch them on once rename over an existing file is confirmed there.
  • IdentityStore::save() now returns whether the write worked instead of always true.
  • Not touched: /adv_blobs (changed in place, littlefs is copy on write), the one-time migration, the packet log (append).

Testing

  • Builds: MeshTracker_X1_companion_radio_ble, MeshTracker_X1_repeater, Heltec_v3_repeater, PicoW_repeater, Tiny_Relay_repeater.
  • native_atomic_file (7 tests, new, with an in-memory LittleFS mock) and native: all pass.
  • Not tested on a device: power loss during a save, and rename over an existing file on real flash.

…rite

On littlefs platforms (nRF52, STM32) a power loss between remove() and the end
of the rewrite lost the file. AtomicFile::write() writes <file>.tmp, checks its
size after close and renames it over the target, so the old file stays until
the new one is complete. If the temp copy does not fit it falls back to the old
in-place behaviour. Orphaned .tmp files are removed on load.

Used by IdentityStore, CommonCLI prefs, ClientACL, RegionMap and the companion
DataStore (prefs, contacts, channels). ESP32 and RP2040 are unchanged unless
MESH_ATOMIC_FS_WRITES is defined. Not tested on a device.

This branch has not been deployed

No deployments
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