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