LFSv2 + Chunked Contacts - #2964
Conversation
|
Thanks for the PR. May I know how this PR solves the root cause of the issue? Thanks a lot and have a nice day. |
|
Hi @IoTThinks, thanks for your interest. The main cause of the filesystem corruption issue is a mismatch of block size to page erase size. LittleFS uses metadata block pairs to avoid corruption during PowerLossOnWrite but because on Adafruit LittleFS the block size is 128 byte vs the page erase of 4kB it's possible to lose both metadata blocks from a pair (or even both superblocks, which causes hang on boot in LittleFSv1). Devices using CustomLFS on external flash already use 4kB blocks which is why you basically never see corruption there. Unfortunately due to metadata overhead there's not really room for 4kB blocks for ExtraFS unless we move to LFSv2. This PR would switch to LittleFSv2 and 4kB blocks for ExtraFS, and also switches to chunked contacts with atomic write instead of a monolithic contacts file. This way any time there is a new contact or updated contact we only write ~4kB of data instead of all of the contacts, and if powerloss happens during the write window we only lose that update instead of the entire file. |
|
Thanks a lot for your detailed information. Let me see how to "replicate" the issue to test on my T1000e. |
The easiest way to force corruption is to make sure you have a full contacts list, and then use another node to send an advert, and then while the T1000e is writing the contacts to flash you reset it by holding the button and briefly disconnecting the USB cable. This will corrupt the filesystem every time, sometimes you lose the contacts file, sometimes the contacts file is there but it's corrupted and can lead to crashes on the next advert arrival, or the worst case scenario it corrupts the superblock pair and the node can't boot. I'll rebase this PR on current dev and force push tomorrow, it will still need more work and testing before it's ready for merge anyway. |
585bace to
afbb489
Compare
added missing declarations for user_btn and NullDisplayDriver
fixes minewsemi repeater failing build due to user_btn missing.
use relocateFile() for file moves and remove old unneeded cleanup logic
afbb489 to
6b06784
Compare
This PR upgrades all LFSv1 filesystems (including UserData) to LFSv2, and in the case of ExtraFS it will reformat to 4kB blocks as well.
The monolithic contacts file is converted into chunks that each fit into a single 4kB block, and all file writes are atomic.
Identity and preferences are migrated to ExtraFS/QSPIFlash, and a "backup" copy of identity is left on UserData just in case. At load time if an identity can't be found on the storage filesystem (ExtraFS/QSPIFlash) an attempt is made to restore identity from UserData.
adv_blobs doesn't make the migration from ExtraFS because there isn't enough space in RAM to store it during the reformat to 4kB blocks. adv_blobs is basically treated as ephemeral data anyway so this shouldn't be an issue.
Maximum adv_blobs is reduced from 100 to 40 in order to free up a few blocks for the overhead required for atomic writes and the metadata compaction that happens occasionally on LFSv2. Could be increased to 45 without any extra block overhead.
I've done quite a bit of testing on nRF (Seeed WioTrackerL1, Seeed T1000e, Heltec T114, Xiao NRF52, and others), and also a limited amount of testing on ESP32, RP2040 and STM32.
Something this huge really needs a lot of testing, so please help out if you're game.
Please add the debug macros
-D MESH_DEBUG=1and-D CFG_DEBUG=1in order to get useful debug prints, especially for the first boot migration process which is where I anticipate issues might be lurking.Best effort is made to migrate your data but better to be safe than sorry, and switching back to any firmware that doesn't support LFSv2 will wipe your filesystems!
Please backup your node before testing this PR!