@@ -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+
199251static 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