Skip to content

Commit 10e6f7f

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. Upstream PR #: 86170 Signed-off-by: Riadh Ghaddab <[email protected]> (cherry picked from commit e56b55885b19628c6944a2544ca724717fbbb7b3)
1 parent b62de40 commit 10e6f7f

File tree

2 files changed

+29
-18
lines changed

2 files changed

+29
-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: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ static int settings_zms_load(struct settings_store *cs, const struct settings_lo
3030
static int settings_zms_save(struct settings_store *cs, const char *name, const char *value,
3131
size_t val_len);
3232
static void *settings_zms_storage_get(struct settings_store *cs);
33+
static int settings_zms_get_last_hash_ids(struct settings_zms *cf);
3334

3435
static 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

397409
int settings_backend_init(void)

0 commit comments

Comments
 (0)