-
Notifications
You must be signed in to change notification settings - Fork 3k
Refactor TDB internal bounds computation #11629
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@kyle-cypress, thank you for your changes. |
Attn @SeppoTakalo @ARMmbed/team-st-mcd |
2814f11
to
d6a1ac6
Compare
MBED_ASSERT(curr_addr >= first_wrtbl_sector_addr); | ||
if (curr_addr < first_wrtbl_sector_addr) { | ||
ret = MBED_ERROR_MEDIA_FULL; | ||
} else { | ||
*start_address = curr_addr; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@SeppoTakalo should we maybe use MBED_ERROR here? To replace all the highlighted lines.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be too big API change.. maybe for the OS version 6.
} | ||
|
||
//Check that internal flash has 2 or more sectors | ||
if (_calculate_blocksize_match_tdbstore(kvstore_config.internal_bd) != MBED_SUCCESS) { | ||
//Check if TDBStore has at least 2 sector. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
*s or 10 pages.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why would 10 pages work instead of a full sector? I think TDBSTore uses the flash sectors to do the garbage collection, in sort of A vs. B, one of them being active and the other one as the spare?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that matches my understanding of TDBStore's garbage collection - it divides the available flash area in half and alternates between the two to do copying GC.
The problem is that the default approach breaks down when the sector size and page sizes are the same (or close), because many of the KVStore operations consume an entire page. Based on our analysis of the KVStore greentea tests as a proxy for typical usage, the minimum page count appeared to be around 10 i.e. 5 pages in active use, 5 in reserve for GC (or 2 sectors if that is larger, so that GC continues to work). If there's a different number of pages that more directly corresponds to something intrinsic in the driver I'd be happy to go with that instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@VeijoPesonen, with regard to:
*s or 10 pages.
Wouldn't expanding this check produce a backwards compatibility concern? Or does this qualify as a situation where it would probably have always failed, just in a less explicit manner, and therefore it is okay to add a new error condition?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@VeijoPesonen, can you please confirm that the expanded check is not a backwards compatibility concern?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi, was browsing some PRs randomly, sorry for jumping in.
The number of pages TDBStore needs depends on the number of KV pairs+1. So for 4 KV pairs it needs 5 pages. (Actually it may need 2 pages per KV pair, not sure).
Unfortunately I think this means you can't make this check unless you know the number of KV pairs beforehand.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree that you can't compute a minimum that is guaranteed to be enough unless you know how much is intended to be stored. However, there is a bare minimum size (e.g. space for internal bookkeeping, a second sector for garbage collection) below which TDBStore cannot function. That is what this check is intended to achieve. Are you saying that the bare minimum page count calculation should be different?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, my understanding was that the theoretical minimum would be 4 pages total (2 for the active master record, 2 for the old master record, where pages = program size'd units). But my understand could be out of date.
Out of curiousity do you know where the other 2x3 pages come from?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I not able to determine precisely where that came from.
However, after further consideration I've removed the hard-fail on too few pages given that the exact minimum is application specific. Full reasoning is in the commit message for a3a4eef59939741999101f1eb5b4367f422f9e6e
@ARMmbed/mbed-os-storage Please help reviewing this PR |
@0xc0170 work in progress, let's give @kyle-cypress time to address the remaining issues. He seems to have a higher priority PR to finish first. |
7455372
to
2899562
Compare
@kyle-cypress This PR was updated, what is the current status? |
There are two items left that I know of:
|
@@ -2,11 +2,11 @@ | |||
"name": "storage_filesystem", | |||
"config": { | |||
"rbp_internal_size": { | |||
"help": "Default is the size of the 2 last sectors of internal flash", | |||
"help": "Default is the larger of the last 2 sectors or last 10 pages of flash.", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You later specify TDBStore ::STORE_PAGES
to 14
, so why this is 10?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because STORE_PAGES was increased and the comment update was missed. I will fix.
tr_warning("KV Config: There are less than two sectors - TDBStore will not work."); | ||
return -1; | ||
} | ||
|
||
if (number_of_page < TDBStore::STORE_PAGES) { | ||
tr_warning("KV Config: There are less than fourteen pages - TDBStore will not work."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be tr_error()
, and preferably change the previous as well.
Also not sure whether TDBStore::STORE_PAGES
can change in the future, so perhaps use less than %d pages
.
#else | ||
return NULL; | ||
#endif | ||
} | ||
|
||
BlockDevice *_get_blockdevice_SPIF(bd_addr_t start_address, bd_size_t size) | ||
BlockDevice *_get_blockdevice_SPIF(bd_addr_t &start_address, bd_size_t &size) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we change the API, should we use pointers instead of references?
Makes it more obvious for caller that the values can change. I don't really like references for trivial types.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I looked through the current changeset and nothing uses the returned value anymore. I will revert the argument type change.
MBED_ASSERT(curr_addr >= first_wrtbl_sector_addr); | ||
if (curr_addr < first_wrtbl_sector_addr) { | ||
ret = MBED_ERROR_MEDIA_FULL; | ||
} else { | ||
*start_address = curr_addr; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be too big API change.. maybe for the OS version 6.
@kyle-cypress Please review the latest comments from @SeppoTakalo |
2899562
to
c52d452
Compare
I've pushed up changes that I believe address all of the remaining change requests. I still need confirmation that the change suggested in #11629 (comment) (it is included in the current changeset) is not a backwards compatibility problem. |
Looks OK. This has already been labeled as 6.0, so I would not worry about being backward compatible. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me
Increase minimum page count from 10 to 14 based on further experiments with features-storage-tests-kvstore-static_tests.
No callers make use of the modified argument values, so change them to a more straightforward pass by value.
Replace custom caluation that always assumed two sectors with the standard calculation exposed on TDBStore.
STORE_SECTORS is a hard requirement. If there are fewer than 2 pages then the kvstore will not work, because the garbage collection process relies on having at least two sectors to work with. STORE_PAGES is a heuristic. It is a reasonable default to use if the application does not specify the amount of flash to use for TDBStore. But if an application knows that a smaller number of pages will suffice for its specific needs, then that is valid and should be permitted.
The unittests compile DirectAccessDeviceKey.cpp which depends on kv_config.h, which lives in features/storage/kvstore/conf
6d730b4
to
85d2e8f
Compare
The unittest failure is because kv_config.h is included from DirectAccessDeviceKey.cpp, but its containing folder is not in the include path for the unittest build. I pushed up 85d2e8f (rebasing again in the process) which adds an entry to UNITTESTS/CMakeLists.txt. This fixed the build when I tested it out locally, but I'm not sure if that is the right place to make this change. |
Also, FYI, the "Build Artifacts" link posted above by mbed-ci still doesn't contain any logs related to failing tests. |
CI restarted |
Test run: FAILEDSummary: 1 of 6 test jobs failed Failed test jobs:
|
The failures for NUCLEO_F429ZI are in network and netsocket, which this PR doesn't touch. Is this a CI issue? |
CI restarted |
Updated PR summary to match the latest template from https://os.mbed.com/docs/mbed-os/v5.15/contributing/workflow.html#pull-request-template |
CI restarted |
hi @kyle-cypress you're still slightly out, see #12472 for current template. May be our docs need a tweak too |
Yes, I think the template in the workflow doc is slightly off. Should be up to date now. |
Test run: SUCCESSSummary: 6 of 6 test jobs passed |
Summary of changes
Refactor internal TDB flash bounds computation to reduce code duplication and to provide more viable default values on parts where the program and erase block sizes are close or identical in value.
The default TDBStore internal flash size is determined as the larger of two flash sectors or 14 flash pages (it previously defaulted to two sectors). This increases the usability of the default size computation on devices where the flash sector and page sizes are close or equal to each other.
Impact of changes
Applications which use TDBStore (or another class which wraps it), and do not explicitly specify a value for
internal_size
instorage_tdb_internal
, will consume additional flash space for TDBStore.Migration actions required
If an application does not already specify
internal_size
forstorage_tdb_internal
in its mbed_app.json, and the increased storage is not desired, add an entry to mbed_app.json to explicitly specify the desired size.If an application already specifies
internal_size
forstorage_tdb_internal
in its mbed_app.json, no changes are required.Documentation
N/A
Pull request type (required)
Test results (required)
Reviewers