@@ -30,6 +30,7 @@ static int settings_zms_load(struct settings_store *cs, const struct settings_lo
3030static int settings_zms_save (struct settings_store * cs , const char * name , const char * value ,
3131 size_t val_len );
3232static void * settings_zms_storage_get (struct settings_store * cs );
33+ static int settings_zms_get_last_hash_ids (struct settings_zms * cf );
3334
3435static struct settings_store_itf settings_zms_itf = {.csi_load = settings_zms_load ,
3536 .csi_save = settings_zms_save ,
@@ -169,18 +170,19 @@ static int settings_zms_load(struct settings_store *cs, const struct settings_lo
169170 * entries one for the setting's name and one with the
170171 * setting's value.
171172 */
172- rc1 = zms_read (& cf -> cf_zms , ZMS_NAME_HASH_ID (ll_hash_id ), & name , sizeof (name ) - 1 );
173+ rc1 = zms_read (& cf -> cf_zms , ZMS_NAME_ID_FROM_LL_NODE (ll_hash_id ), & name ,
174+ sizeof (name ) - 1 );
173175 /* get the length of data and verify that it exists */
174- rc2 = zms_get_data_length (& cf -> cf_zms ,
175- ZMS_NAME_HASH_ID ( ll_hash_id ) + ZMS_DATA_ID_OFFSET );
176+ rc2 = zms_get_data_length (& cf -> cf_zms , ZMS_NAME_ID_FROM_LL_NODE ( ll_hash_id ) +
177+ ZMS_DATA_ID_OFFSET );
176178
177179 if ((rc1 <= 0 ) || (rc2 <= 0 )) {
178180 /* Settings item is not stored correctly in the ZMS.
179181 * ZMS entry for its name or value is either missing
180182 * or deleted. Clean dirty entries to make space for
181183 * future settings item.
182184 */
183- ret = settings_zms_delete (cf , ZMS_NAME_HASH_ID (ll_hash_id ));
185+ ret = settings_zms_delete (cf , ZMS_NAME_ID_FROM_LL_NODE (ll_hash_id ));
184186 if (ret < 0 ) {
185187 return ret ;
186188 }
@@ -190,7 +192,7 @@ static int settings_zms_load(struct settings_store *cs, const struct settings_lo
190192 /* Found a name, this might not include a trailing \0 */
191193 name [rc1 ] = '\0' ;
192194 read_fn_arg .fs = & cf -> cf_zms ;
193- read_fn_arg .id = ZMS_NAME_HASH_ID (ll_hash_id ) + ZMS_DATA_ID_OFFSET ;
195+ read_fn_arg .id = ZMS_NAME_ID_FROM_LL_NODE (ll_hash_id ) + ZMS_DATA_ID_OFFSET ;
194196
195197 ret = settings_call_set_handler (name , rc2 , settings_zms_read_fn , & read_fn_arg ,
196198 (void * )arg );
@@ -232,8 +234,10 @@ static int settings_zms_save(struct settings_store *cs, const char *name, const
232234 delete = ((value == NULL ) || (val_len == 0 ));
233235
234236 name_hash = sys_hash32 (name , strlen (name )) & ZMS_HASH_MASK ;
237+ /* MSB is always 1 */
238+ name_hash |= BIT (31 );
235239
236- /* Let's find out if there is no hash collisions in the storage */
240+ /* Let's find out if there are hash collisions in the storage */
237241 write_name = true;
238242 hash_collision = true;
239243
@@ -311,6 +315,16 @@ static int settings_zms_save(struct settings_store *cs, const char *name, const
311315 }
312316 /* write linked list structure element */
313317 settings_element .next_hash = 0 ;
318+ /* Verify first that the linked list last element is not broken.
319+ * Settings subsystem uses ID that starts from ZMS_LL_HEAD_HASH_ID.
320+ */
321+ if (cf -> last_hash_id < ZMS_LL_HEAD_HASH_ID ) {
322+ LOG_WRN ("Linked list for hashes is broken, Trying to recover" );
323+ rc = settings_zms_get_last_hash_ids (cf );
324+ if (rc < 0 ) {
325+ return rc ;
326+ }
327+ }
314328 settings_element .previous_hash = cf -> last_hash_id ;
315329 rc = zms_write (& cf -> cf_zms , name_hash | 1 , & settings_element ,
316330 sizeof (struct settings_hash_linked_list ));
@@ -342,9 +356,22 @@ static int settings_zms_get_last_hash_ids(struct settings_zms *cf)
342356 do {
343357 rc = zms_read (& cf -> cf_zms , ll_last_hash_id , & settings_element ,
344358 sizeof (settings_element ));
345- if (rc ) {
359+ if (rc == - ENOENT ) {
360+ /* header doesn't exist or linked list broken, reinitialize the header */
361+ const struct settings_hash_linked_list settings_element = {
362+ .previous_hash = 0 , .next_hash = 0 };
363+ rc = zms_write (& cf -> cf_zms , ZMS_LL_HEAD_HASH_ID , & settings_element ,
364+ sizeof (struct settings_hash_linked_list ));
365+ if (rc < 0 ) {
366+ return rc ;
367+ }
368+ cf -> last_hash_id = ZMS_LL_HEAD_HASH_ID ;
369+ cf -> second_to_last_hash_id = 0 ;
370+ return 0 ;
371+ } else if (rc < 0 ) {
346372 return rc ;
347373 }
374+
348375 /* increment hash collision number if necessary */
349376 if (ZMS_COLLISION_NUM (ll_last_hash_id ) > cf -> hash_collision_num ) {
350377 cf -> hash_collision_num = ZMS_COLLISION_NUM (ll_last_hash_id );
@@ -375,23 +402,9 @@ static int settings_zms_backend_init(struct settings_zms *cf)
375402 cf -> hash_collision_num = 0 ;
376403
377404 rc = settings_zms_get_last_hash_ids (cf );
378- if (rc == - ENOENT ) {
379- /* header doesn't exist or linked list broken, reinitialize the header */
380- const struct settings_hash_linked_list settings_element = {.previous_hash = 0 ,
381- .next_hash = 0 };
382- rc = zms_write (& cf -> cf_zms , ZMS_LL_HEAD_HASH_ID , & settings_element ,
383- sizeof (struct settings_hash_linked_list ));
384- if (rc < 0 ) {
385- return rc ;
386- }
387- cf -> last_hash_id = ZMS_LL_HEAD_HASH_ID ;
388- cf -> second_to_last_hash_id = 0 ;
389- } else if (rc < 0 ) {
390- return rc ;
391- }
392405
393406 LOG_DBG ("ZMS backend initialized" );
394- return 0 ;
407+ return rc ;
395408}
396409
397410int settings_backend_init (void )
0 commit comments