Skip to content

Commit 3a7a45d

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 fbb212770ee3c01a38b34b7e4e68a2801ca8a95b)
1 parent 51c0faf commit 3a7a45d

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
@@ -197,6 +197,58 @@ static int settings_zms_delete(struct settings_zms *cf, uint32_t name_hash)
197197
return rc;
198198
}
199199

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

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

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

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

0 commit comments

Comments
 (0)