@@ -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 ,
@@ -232,6 +233,8 @@ static int settings_zms_save(struct settings_store *cs, const char *name, const
232233 delete = ((value == NULL ) || (val_len == 0 ));
233234
234235 name_hash = sys_hash32 (name , strlen (name )) & ZMS_HASH_MASK ;
236+ /* MSB is always 1 */
237+ name_hash |= BIT (31 );
235238
236239 /* Let's find out if there is no hash collisions in the storage */
237240 write_name = true;
@@ -311,6 +314,16 @@ static int settings_zms_save(struct settings_store *cs, const char *name, const
311314 }
312315 /* write linked list structure element */
313316 settings_element .next_hash = 0 ;
317+ /* Verify first that the linked list last element is not broken.
318+ * Settings subsystem uses ID that starts from ZMS_LL_HEAD_HASH_ID.
319+ */
320+ if (cf -> last_hash_id < ZMS_LL_HEAD_HASH_ID ) {
321+ LOG_WRN ("Linked list for hashes is broken, Trying to recover" );
322+ rc = settings_zms_get_last_hash_ids (cf );
323+ if (rc < 0 ) {
324+ return rc ;
325+ }
326+ }
314327 settings_element .previous_hash = cf -> last_hash_id ;
315328 rc = zms_write (& cf -> cf_zms , name_hash | 1 , & settings_element ,
316329 sizeof (struct settings_hash_linked_list ));
@@ -342,9 +355,22 @@ static int settings_zms_get_last_hash_ids(struct settings_zms *cf)
342355 do {
343356 rc = zms_read (& cf -> cf_zms , ll_last_hash_id , & settings_element ,
344357 sizeof (settings_element ));
345- if (rc ) {
358+ if (rc == - ENOENT ) {
359+ /* header doesn't exist or linked list broken, reinitialize the header */
360+ const struct settings_hash_linked_list settings_element = {
361+ .previous_hash = 0 , .next_hash = 0 };
362+ rc = zms_write (& cf -> cf_zms , ZMS_LL_HEAD_HASH_ID , & settings_element ,
363+ sizeof (struct settings_hash_linked_list ));
364+ if (rc < 0 ) {
365+ return rc ;
366+ }
367+ cf -> last_hash_id = ZMS_LL_HEAD_HASH_ID ;
368+ cf -> second_to_last_hash_id = 0 ;
369+ return 0 ;
370+ } else if (rc < 0 ) {
346371 return rc ;
347372 }
373+
348374 /* increment hash collision number if necessary */
349375 if (ZMS_COLLISION_NUM (ll_last_hash_id ) > cf -> hash_collision_num ) {
350376 cf -> hash_collision_num = ZMS_COLLISION_NUM (ll_last_hash_id );
@@ -375,23 +401,9 @@ static int settings_zms_backend_init(struct settings_zms *cf)
375401 cf -> hash_collision_num = 0 ;
376402
377403 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- }
392404
393405 LOG_DBG ("ZMS backend initialized" );
394- return 0 ;
406+ return rc ;
395407}
396408
397409int settings_backend_init (void )
0 commit comments