Skip to content

Commit b12dac3

Browse files
committed
[nrf fromlist] settings: zms: fix some bugs related to the name's ID
To avoid collisions between IDs used by settings and IDs used directly by subsystems using ZMS API, the MSB is always set to 1 for Setting's name ID written to ZMS backend Add as well a recovery path if the hash linked list is broken. Signed-off-by: Riadh Ghaddab <[email protected]> (cherry picked from commit e1b84d9f5e09e668742d115ca2252f5afa885abd)
1 parent 6279ad3 commit b12dac3

File tree

2 files changed

+28
-18
lines changed

2 files changed

+28
-18
lines changed

subsys/settings/include/settings/settings_zms.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,9 @@ extern "C" {
6060
#define ZMS_COLLISIONS_MASK GENMASK(CONFIG_SETTINGS_ZMS_MAX_COLLISIONS_BITS, 1)
6161
#define ZMS_HASH_TOTAL_MASK GENMASK(29, 1)
6262
#define ZMS_MAX_COLLISIONS (BIT(CONFIG_SETTINGS_ZMS_MAX_COLLISIONS_BITS) - 1)
63-
#define ZMS_HEADER_HASH 0x80000000
6463

6564
/* some useful macros */
66-
#define ZMS_NAME_HASH_ID(x) (x & ZMS_HASH_TOTAL_MASK)
65+
#define ZMS_NAME_HASH_ID(x) ((x & ZMS_HASH_TOTAL_MASK) | BIT(31))
6766
#define ZMS_UPDATE_COLLISION_NUM(x, y) \
6867
((x & ~ZMS_COLLISIONS_MASK) | ((y << 1) & ZMS_COLLISIONS_MASK))
6968
#define ZMS_COLLISION_NUM(x) ((x & ZMS_COLLISIONS_MASK) >> 1)

subsys/settings/src/settings_zms.c

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -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

397408
int settings_backend_init(void)

0 commit comments

Comments
 (0)