Skip to content

Commit 736a62a

Browse files
committed
settings: zms: add option to disable updating linked list
When deleting a settings entry the linked list is updated by removing the deleted node. This operation is time consuming and add some delays. For applications that use almost the same set of Setting entries, add an option to make this operation faster at a cost of having some empty nodes in the linked list. These empty nodes can be used later when the deleted entry is written again. Each empty node occupies 16B of storage. Signed-off-by: Riadh Ghaddab <[email protected]>
1 parent 44ff312 commit 736a62a

File tree

2 files changed

+60
-33
lines changed

2 files changed

+60
-33
lines changed

subsys/settings/Kconfig

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,17 @@ config SETTINGS_ZMS_MAX_COLLISIONS_BITS
190190
The maximum number of hash collisions needs to be well sized depending
191191
on the data that is going to be stored in ZMS and its hash values
192192

193+
config SETTINGS_ZMS_NO_LL_DELETE
194+
bool "Disable deletion of Linked list hashes"
195+
help
196+
For some applications, the Settings delete operation is too long for
197+
ZMS because of the linked list update.
198+
As a tradeoff for performance the linked list is not updated. As a
199+
result, some nodes will be unused and will occupy some space in the
200+
storage.
201+
These nodes will be used again when the same Settings element that has
202+
been deleted is created again.
203+
193204
config SETTINGS_SHELL
194205
bool "Settings shell"
195206
depends on SHELL

subsys/settings/src/settings_zms.c

Lines changed: 49 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ static int settings_zms_dst(struct settings_zms *cf)
6161
return 0;
6262
}
6363

64+
#ifndef CONFIG_SETTINGS_ZMS_NO_LL_DELETE
6465
static int settings_zms_unlink_ll_node(struct settings_zms *cf, uint32_t name_hash)
6566
{
6667
int rc = 0;
@@ -119,32 +120,7 @@ static int settings_zms_unlink_ll_node(struct settings_zms *cf, uint32_t name_ha
119120

120121
return rc;
121122
}
122-
123-
static int settings_zms_delete(struct settings_zms *cf, uint32_t name_hash)
124-
{
125-
int rc = 0;
126-
127-
rc = zms_delete(&cf->cf_zms, name_hash);
128-
if (rc >= 0) {
129-
rc = zms_delete(&cf->cf_zms, name_hash + ZMS_DATA_ID_OFFSET);
130-
}
131-
if (rc < 0) {
132-
return rc;
133-
}
134-
135-
rc = settings_zms_unlink_ll_node(cf, name_hash);
136-
if (rc < 0) {
137-
return rc;
138-
}
139-
140-
/* Now delete the current linked list element */
141-
rc = zms_delete(&cf->cf_zms, name_hash | 1);
142-
if (rc < 0) {
143-
return rc;
144-
}
145-
146-
return rc;
147-
}
123+
#endif /* CONFIG_SETTINGS_ZMS_NO_LL_DELETE */
148124

149125
#if CONFIG_SETTINGS_ZMS_NAME_CACHE
150126
static void settings_zms_cache_add(struct settings_zms *cf, uint32_t name_hash, uint8_t flags)
@@ -194,6 +170,7 @@ static int settings_zms_delete(struct settings_zms *cf, uint32_t name_hash)
194170
if (rc < 0) {
195171
return rc;
196172
}
173+
#ifndef CONFIG_SETTINGS_ZMS_NO_LL_DELETE
197174
rc = settings_zms_unlink_ll_node(cf, name_hash);
198175
if (rc < 0) {
199176
return rc;
@@ -204,15 +181,16 @@ static int settings_zms_delete(struct settings_zms *cf, uint32_t name_hash)
204181
if (rc < 0) {
205182
return rc;
206183
}
207-
184+
#endif /* CONFIG_SETTINGS_ZMS_NO_LL_DELETE */
208185
#ifdef CONFIG_SETTINGS_ZMS_NAME_CACHE
209186
/* Update the flag of the Settings entry in cache. */
210187
uint8_t cache_flags = 0;
211188

212189
if (ZMS_COLLISION_NUM(name_hash) > 0) {
190+
/* indicates that it has a hash collision */
213191
cache_flags |= BIT(1);
214192
}
215-
/* set the delete BIT(1) indicating that the entry is deleted. */
193+
/* set the delete BIT(2) indicating that the entry is deleted. */
216194
cache_flags |= BIT(2);
217195
settings_zms_cache_add(cf, name_hash & ZMS_HASH_MASK, cache_flags);
218196
#endif
@@ -249,15 +227,26 @@ static int settings_zms_load(struct settings_store *cs, const struct settings_lo
249227
ZMS_NAME_HASH_ID(ll_hash_id) + ZMS_DATA_ID_OFFSET);
250228

251229
if ((rc1 <= 0) || (rc2 <= 0)) {
252-
/* Settings item is not stored correctly in the ZMS.
253-
* ZMS entry for its name or value is either missing
254-
* or deleted. Clean dirty entries to make space for
255-
* future settings item.
230+
/* In case we are not updating the linked list, this is an empty mode
231+
* Just continue
232+
*/
233+
#ifndef CONFIG_SETTINGS_ZMS_NO_LL_DELETE
234+
/* Otherwise, Settings item is not stored correctly in the ZMS.
235+
* ZMS entry for its name or value is either missing or deleted.
236+
* Clean dirty entries to make space for future settings item.
256237
*/
257238
ret = settings_zms_delete(cf, ZMS_NAME_HASH_ID(ll_hash_id));
258239
if (ret < 0) {
259240
return ret;
260241
}
242+
#endif /* CONFIG_SETTINGS_ZMS_NO_LL_DELETE */
243+
/* update next ll_hash_id */
244+
ret = zms_read(&cf->cf_zms, ll_hash_id, &settings_element,
245+
sizeof(struct settings_hash_linked_list));
246+
if (ret < 0) {
247+
return ret;
248+
}
249+
ll_hash_id = settings_element.next_hash;
261250
continue;
262251
}
263252

@@ -305,6 +294,9 @@ static int settings_zms_save(struct settings_store *cs, const char *name, const
305294
bool write_name;
306295
int rc = 0;
307296
int first_available_hash_index = -1;
297+
#ifdef CONFIG_SETTINGS_ZMS_NO_LL_DELETE
298+
bool ll_node_exist = false;
299+
#endif /* CONFIG_SETTINGS_ZMS_NO_LL_DELETE */
308300

309301
if (!name) {
310302
return -EINVAL;
@@ -327,11 +319,18 @@ static int settings_zms_save(struct settings_store *cs, const char *name, const
327319
} else {
328320
write_name = false;
329321
}
322+
#ifdef CONFIG_SETTINGS_ZMS_NO_LL_DELETE
323+
/* In this case the settings entry is deleted, which means that
324+
* its linked list node still exist in this case and do not need
325+
* to be updated.
326+
*/
327+
ll_node_exist = true;
328+
#endif /* CONFIG_SETTINGS_ZMS_NO_LL_DELETE */
330329
goto no_hash_collision;
331330
}
332331
#endif
333332

334-
/* Let's find out if there is no hash collisions in the storage */
333+
/* Let's find out if there are hash collisions in the storage */
335334
write_name = true;
336335

337336
for (int i = 0; i <= cf->hash_collision_num; i++) {
@@ -405,6 +404,20 @@ static int settings_zms_save(struct settings_store *cs, const char *name, const
405404
if (rc < 0) {
406405
return rc;
407406
}
407+
#ifdef CONFIG_SETTINGS_ZMS_NO_LL_DELETE
408+
if (ll_node_exist) {
409+
goto no_ll_update;
410+
}
411+
/* verify that the ll_node doesn't exist otherwise do not update it */
412+
rc = zms_read(&cf->cf_zms, name_hash | 1, &settings_element,
413+
sizeof(struct settings_hash_linked_list));
414+
if (rc >= 0) {
415+
goto no_ll_update;
416+
} else if (rc != -ENOENT) {
417+
return rc;
418+
}
419+
/* else the LL node doesn't exist let's update it */
420+
#endif /* CONFIG_SETTINGS_ZMS_NO_LL_DELETE */
408421
/* write linked list structure element */
409422
settings_element.next_hash = 0;
410423
/* Verify first that the linked list last element is not broken.
@@ -434,6 +447,9 @@ static int settings_zms_save(struct settings_store *cs, const char *name, const
434447
cf->second_to_last_hash_id = cf->last_hash_id;
435448
cf->last_hash_id = name_hash | 1;
436449
}
450+
#ifdef CONFIG_SETTINGS_ZMS_NO_LL_DELETE
451+
no_ll_update:
452+
#endif /* CONFIG_SETTINGS_ZMS_NO_LL_DELETE */
437453
#ifdef CONFIG_SETTINGS_ZMS_NAME_CACHE
438454
/* Add the flags of the written settings entry in cache */
439455
cache_flags = 0;

0 commit comments

Comments
 (0)