@@ -232,6 +232,8 @@ static int settings_zms_save(struct settings_store *cs, const char *name, const
232232 delete = ((value == NULL ) || (val_len == 0 ));
233233
234234 name_hash = sys_hash32 (name , strlen (name )) & ZMS_HASH_MASK ;
235+ /* MSB is always 1 */
236+ name_hash |= BIT (31 );
235237
236238 /* Let's find out if there is no hash collisions in the storage */
237239 write_name = true;
@@ -311,6 +313,16 @@ static int settings_zms_save(struct settings_store *cs, const char *name, const
311313 }
312314 /* write linked list structure element */
313315 settings_element .next_hash = 0 ;
316+ /* Verify first that the linked list last element is not broken.
317+ * Settings subsystem uses ID that starts from ZMS_LL_HEAD_HASH_ID.
318+ */
319+ if (cf -> last_hash_id < ZMS_LL_HEAD_HASH_ID ) {
320+ LOG_WARN ("Linked list for hashes is broken, Trying to recover" );
321+ rc = settings_zms_get_last_hash_ids (cf );
322+ if (rc < 0 ) {
323+ return rc ;
324+ }
325+ }
314326 settings_element .previous_hash = cf -> last_hash_id ;
315327 rc = zms_write (& cf -> cf_zms , name_hash | 1 , & settings_element ,
316328 sizeof (struct settings_hash_linked_list ));
@@ -342,9 +354,22 @@ static int settings_zms_get_last_hash_ids(struct settings_zms *cf)
342354 do {
343355 rc = zms_read (& cf -> cf_zms , ll_last_hash_id , & settings_element ,
344356 sizeof (settings_element ));
345- if (rc ) {
357+ if (rc == - ENOENT ) {
358+ /* header doesn't exist or linked list broken, reinitialize the header */
359+ const struct settings_hash_linked_list settings_element = {
360+ .previous_hash = 0 , .next_hash = 0 };
361+ rc = zms_write (& cf -> cf_zms , ZMS_LL_HEAD_HASH_ID , & settings_element ,
362+ sizeof (struct settings_hash_linked_list ));
363+ if (rc < 0 ) {
364+ return rc ;
365+ }
366+ cf -> last_hash_id = ZMS_LL_HEAD_HASH_ID ;
367+ cf -> second_to_last_hash_id = 0 ;
368+ return 0 ;
369+ } else if (rc < 0 ) {
346370 return rc ;
347371 }
372+
348373 /* increment hash collision number if necessary */
349374 if (ZMS_COLLISION_NUM (ll_last_hash_id ) > cf -> hash_collision_num ) {
350375 cf -> hash_collision_num = ZMS_COLLISION_NUM (ll_last_hash_id );
@@ -375,23 +400,9 @@ static int settings_zms_backend_init(struct settings_zms *cf)
375400 cf -> hash_collision_num = 0 ;
376401
377402 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- }
392403
393404 LOG_DBG ("ZMS backend initialized" );
394- return 0 ;
405+ return rc ;
395406}
396407
397408int settings_backend_init (void )
0 commit comments