Currently when page is being freed, items are individually moved from
FREEING page to ACTIVE page and erased. If power-off happens during the
process, the remaining entries are moved to ACTIVE page during recovery.
The problem with this approach is there may not be enough space on
ACTIVE page for all items if an item was partially written before
power-off and erased during recovery. This change moves all the items
from FREEING to ACTIVE page and then erased the FREEING page, If
power-off happens during the process, then ACTIVE page is erased and the
process is restarted.
Current page selection algorithm selects a page for compaction based on just erased counts
and gives up when it does not find any page with erased count greater than 0. This is
problematic since the current allocation procedure skips the active page if there is not
enough room for the item in that page leaving free chunks on the pages. This change modifies
the algorithm to consider both erased as well as free counts on the candidate pages.
Closes TW<20297>
Users needs functions to count the number of free and used entries.
1. `nvs_get_stats()` This function return structure of statistic about the uspace NVS.
(Struct: used_entries, free_entries, total_entries and namespace_count)
2. `nvs_get_used_entry_count()` The second function return amount of entries in the namespace (by handler)
3. Added unit tests.
Closes TW<12282>
This change adds a check for the free page count to nvs_flash_init.
Under normal operation, NVS keeps at least one free page available,
except for transient states such as freeing up new page. Due to external
factors (such as NVS partition size reduction) this free page could be
lost, making NVS operation impossible. Previously this would cause an
error when performing any nvs_set operation or opening a new namespace.
With this change, an error is returned from nvs_flash_init to indicate
that NVS partition is in such a state.
One common pattern of using assert function looks as follows:
int ret = do_foo();
assert(ret == 0); // which reads as: “do_foo should never fail here, by design”
The problem with such code is that if ‘assert’ is removed by the preprocessor in release build,
variable ret is no longer used, and the compiler issues a warning about this.
Changing assert definition in the way done here make the variable used, from language syntax perspective.
Semantically, the variable is still unused at run time (as sizeof can be evaluated at compile time), so the compiler
can optimize things away if possible.
This commit fixes several issues with state handling in nvs::Page. It also adds extra consistency checks in nvs::PageManger initialization.
These changes were verified with a new long-running test ("test recovery from sudden poweroff"). This test works by repeatedly performing same pseudorandom sequence of calls to nvs_ APIs. Each time it repeats the sequence, it introduces a failure into one of flash operations (write or erase). So if one iteration of this test needs, say, 25000 flash operations, then this test will run 25000 iterations, each time introducing the failure point at different location.