Skip to content

Commit

Permalink
fs: nvs: Add recovery path for corrupted NVS
Browse files Browse the repository at this point in the history
When all sectors of the settings partition have some data that is not 0xFF, NVS will fail to initialize settings. Add a recovery path to erase the whole settings partition and recover. Should not happen unless there's some serious flash corruption, or possibly interrupted garbage collection. Verified by recreating the scenario with flash CLIs.

Signed-off-by: Cory Andrew Mayer <[email protected]>
  • Loading branch information
corymayer committed Dec 19, 2024
1 parent 798122e commit 10760e6
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 1 deletion.
8 changes: 8 additions & 0 deletions subsys/fs/nvs/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,14 @@ config NVS_DATA_CRC
The CRC-32 is transparently stored at the end of the data field,
in the NVS data section, so 4 more bytes are needed per NVS element.

config NVS_INIT_BAD_MEMORY_REGION
bool "Non-volatile Storage bad memory region recovery"
help
Enable automatic initialization of a NVS on a memory region that does
not contain a valid NVS. A region containing an invalid NVS can be
caused by corruption or by providing a non-empty region. This option
ensures a new NVS can be created.

module = NVS
module-str = nvs
source "subsys/logging/Kconfig.template.log_config"
Expand Down
15 changes: 14 additions & 1 deletion subsys/fs/nvs/nvs.c
Original file line number Diff line number Diff line change
Expand Up @@ -781,10 +781,23 @@ static int nvs_startup(struct nvs_fs *fs)
}
}
}
/* all sectors are closed, this is not a nvs fs */
/* all sectors are closed, this is not a nvs fs or irreparably corrupted */
if (closed_sectors == fs->sector_count) {
#ifdef CONFIG_NVS_INIT_BAD_MEMORY_REGION
LOG_WRN("All sectors closed, erasing all sectors...");
rc = flash_flatten(fs->flash_device, fs->offset,
fs->sector_size * fs->sector_count);
if (rc) {
goto end;
}

i = fs->sector_count;
addr = ((fs->sector_count - 1) << ADDR_SECT_SHIFT) +
(uint16_t)(fs->sector_size - ate_size);
#else
rc = -EDEADLK;
goto end;
#endif
}

if (i == fs->sector_count) {
Expand Down

0 comments on commit 10760e6

Please sign in to comment.