Skip to content

Commit 52ad406

Browse files
committed
[nrf fromlist] settings: zms: load only subtree in the argument
If the subtree argument is not NULL in the settings_load function, load only the setting entry that corresponds to that subtree. If the subtree argument is NULL or it is not found in the storage, load all the existing entries in the storage. Upstream PR #: 87792 Signed-off-by: Riadh Ghaddab <[email protected]> (cherry picked from commit ee9df348f12e0e395f017110243ce338e04204b1)
1 parent 0423d9b commit 52ad406

File tree

3 files changed

+74
-1
lines changed

3 files changed

+74
-1
lines changed

subsys/settings/Kconfig

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,16 @@ config SETTINGS_ZMS_NO_LL_DELETE
201201
These nodes will be used again when the same Settings element that has
202202
been deleted is created again.
203203

204+
config SETTINGS_ZMS_LOAD_SUBTREE_PATH
205+
bool "Load only subtree path if provided"
206+
help
207+
Some applications use the settings_load_subtree to load only one
208+
settings entry instead of a all entries under that path.
209+
Enabling this config will allow the ZMS backend to try to load that
210+
path first.
211+
If the callback handler returns a zero value it will
212+
continue to look for all the keys under that subtree path.
213+
204214
config SETTINGS_SHELL
205215
bool "Settings shell"
206216
depends on SHELL

subsys/settings/include/settings/settings_zms.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,8 @@ extern "C" {
7474
#define ZMS_NAME_ID_FROM_LL_NODE(x) (x & ~BIT(0))
7575
#define ZMS_UPDATE_COLLISION_NUM(x, y) \
7676
((x & ~ZMS_COLLISIONS_MASK) | ((y << 1) & ZMS_COLLISIONS_MASK))
77-
#define ZMS_COLLISION_NUM(x) ((x & ZMS_COLLISIONS_MASK) >> 1)
77+
#define ZMS_COLLISION_NUM(x) ((x & ZMS_COLLISIONS_MASK) >> 1)
78+
#define ZMS_NAME_ID_FROM_HASH(x) ((x & ZMS_HASH_TOTAL_MASK) | BIT(31))
7879

7980
struct settings_zms {
8081
struct settings_store cf_store;

subsys/settings/src/settings_zms.c

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,58 @@ static int settings_zms_delete(struct settings_zms *cf, uint32_t name_hash)
196196
return rc;
197197
}
198198

199+
#ifdef CONFIG_SETTINGS_ZMS_LOAD_SUBTREE_PATH
200+
/* Loads only the key which is defined by the name found in "subtree".
201+
* This function doesn't look for all the subtrees under the path defined by "subtree".
202+
* It is used to accelerate reads for applications using settings_load_subtree to load
203+
* only one key instead of the whole subtree.
204+
*/
205+
static int settings_zms_load_subtree(struct settings_store *cs, const struct settings_load_arg *arg)
206+
{
207+
struct settings_zms *cf = CONTAINER_OF(cs, struct settings_zms, cf_store);
208+
struct settings_zms_read_fn_arg read_fn_arg;
209+
char name[SETTINGS_MAX_NAME_LEN + SETTINGS_EXTRA_LEN + 1];
210+
ssize_t rc1;
211+
ssize_t rc2;
212+
uint32_t name_hash;
213+
int ret = 0;
214+
215+
name_hash = sys_hash32(arg->subtree, strlen(arg->subtree)) & ZMS_HASH_MASK;
216+
for (int i = 0; i <= cf->hash_collision_num; i++) {
217+
name_hash = ZMS_UPDATE_COLLISION_NUM(name_hash, i);
218+
/* Get the name entry from ZMS */
219+
rc1 = zms_read(&cf->cf_zms, ZMS_NAME_ID_FROM_HASH(name_hash), &name,
220+
sizeof(name) - 1);
221+
/* get the length of data and verify that it exists */
222+
rc2 = zms_get_data_length(&cf->cf_zms,
223+
ZMS_NAME_ID_FROM_HASH(name_hash) + ZMS_DATA_ID_OFFSET);
224+
if ((rc1 <= 0) || (rc2 <= 0)) {
225+
/* Name or data doesn't exist */
226+
continue;
227+
}
228+
/* Found a name, this might not include a trailing \0 */
229+
name[rc1] = '\0';
230+
if (strcmp(arg->subtree, name)) {
231+
/* Names are not equal let's continue to the next collision hash
232+
* if it exists.
233+
*/
234+
continue;
235+
}
236+
/* At this steps the names are equal, let's set the handler */
237+
read_fn_arg.fs = &cf->cf_zms;
238+
read_fn_arg.id = ZMS_NAME_ID_FROM_HASH(name_hash) + ZMS_DATA_ID_OFFSET;
239+
240+
ret = settings_call_set_handler(arg->subtree, rc2, settings_zms_read_fn, &read_fn_arg,
241+
(void *)arg);
242+
/* We should return here as there are no need to look for the next
243+
* hash collision */
244+
return ret;
245+
}
246+
247+
return 0;
248+
}
249+
#endif /* CONFIG_SETTINGS_ZMS_LOAD_SUBTREE_PATH */
250+
199251
static int settings_zms_load(struct settings_store *cs, const struct settings_load_arg *arg)
200252
{
201253
int ret = 0;
@@ -206,6 +258,15 @@ static int settings_zms_load(struct settings_store *cs, const struct settings_lo
206258
ssize_t rc1;
207259
ssize_t rc2;
208260
uint32_t ll_hash_id;
261+
#ifdef CONFIG_SETTINGS_ZMS_LOAD_SUBTREE_PATH
262+
/* If arg->subtree is not null we must load settings in that subtree */
263+
if (arg->subtree != NULL) {
264+
ret = settings_zms_load_subtree(cs, arg);
265+
if (ret) {
266+
return ret;
267+
}
268+
}
269+
#endif /* CONFIG_SETTINGS_ZMS_LOAD_SUBTREE_PATH */
209270

210271
ret = zms_read(&cf->cf_zms, ZMS_LL_HEAD_HASH_ID, &settings_element,
211272
sizeof(struct settings_hash_linked_list));
@@ -214,6 +275,7 @@ static int settings_zms_load(struct settings_store *cs, const struct settings_lo
214275
}
215276
ll_hash_id = settings_element.next_hash;
216277

278+
/* If subtree is NULL then we must load all found Settings */
217279
while (ll_hash_id) {
218280

219281
/* In the ZMS backend, each setting item is stored in two ZMS

0 commit comments

Comments
 (0)