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 18, 2024
1 parent 798122e commit b6fe8e7
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_REGION
bool "Non-volatile Storage bad partition recovery"
help
Enable automatic initialization of a NVS on a flash 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_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 b6fe8e7

Please sign in to comment.