Skip to content

Commit dd8d6fc

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 5da044c commit dd8d6fc

File tree

2 files changed

+53
-7
lines changed

2 files changed

+53
-7
lines changed

subsys/settings/Kconfig

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,18 @@ 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+
default y
196+
help
197+
For some applications, the Settings delete operation is too long for
198+
ZMS because of the linked list update.
199+
As a tradeoff for performance the linked list is not updated. As a
200+
result, some nodes will be unused and will occupy some space in the
201+
storage.
202+
These nodes will be used again when the same Settings element that has
203+
been deleted is created again.
204+
193205
config SETTINGS_SHELL
194206
bool "Settings shell"
195207
depends on SHELL

subsys/settings/src/settings_zms.c

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ static int settings_zms_save(struct settings_store *cs, const char *name, const
3131
size_t val_len);
3232
static void *settings_zms_storage_get(struct settings_store *cs);
3333
static int settings_zms_get_last_hash_ids(struct settings_zms *cf);
34+
static void settings_zms_cache_add(struct settings_zms *cf, uint32_t name_hash, bool has_collision);
3435

3536
static struct settings_store_itf settings_zms_itf = {.csi_load = settings_zms_load,
3637
.csi_save = settings_zms_save,
@@ -61,6 +62,7 @@ static int settings_zms_dst(struct settings_zms *cf)
6162
return 0;
6263
}
6364

65+
#ifndef CONFIG_SETTINGS_ZMS_NO_LL_DELETE
6466
static int settings_zms_unlink_ll_node(struct settings_zms *cf, uint32_t name_hash)
6567
{
6668
int rc = 0;
@@ -119,6 +121,7 @@ static int settings_zms_unlink_ll_node(struct settings_zms *cf, uint32_t name_ha
119121

120122
return rc;
121123
}
124+
#endif /* CONFIG_SETTINGS_ZMS_NO_LL_DELETE */
122125

123126
static int settings_zms_delete(struct settings_zms *cf, uint32_t name_hash)
124127
{
@@ -131,7 +134,7 @@ static int settings_zms_delete(struct settings_zms *cf, uint32_t name_hash)
131134
if (rc < 0) {
132135
return rc;
133136
}
134-
137+
#ifndef CONFIG_SETTINGS_ZMS_NO_LL_DELETE
135138
rc = settings_zms_unlink_ll_node(cf, name_hash);
136139
if (rc < 0) {
137140
return rc;
@@ -142,7 +145,14 @@ static int settings_zms_delete(struct settings_zms *cf, uint32_t name_hash)
142145
if (rc < 0) {
143146
return rc;
144147
}
148+
#endif /* CONFIG_SETTINGS_ZMS_NO_LL_DELETE */
145149

150+
#if defined(CONFIG_SETTINGS_ZMS_NAME_CACHE) && defined (CONFIG_SETTINGS_ZMS_NO_LL_DELETE)
151+
/* This will invalidate the name_hash in cache and will force reading it again when
152+
* writing the same name.
153+
*/
154+
settings_zms_cache_add(cf, name_hash & ZMS_HASH_MASK, 1);
155+
#endif
146156
return rc;
147157
}
148158

@@ -212,15 +222,26 @@ static int settings_zms_load(struct settings_store *cs, const struct settings_lo
212222
ZMS_NAME_HASH_ID(ll_hash_id) + ZMS_DATA_ID_OFFSET);
213223

214224
if ((rc1 <= 0) || (rc2 <= 0)) {
215-
/* Settings item is not stored correctly in the ZMS.
216-
* ZMS entry for its name or value is either missing
217-
* or deleted. Clean dirty entries to make space for
218-
* future settings item.
225+
/* In case we are not updating the linked list, this is an empty mode
226+
* Just continue
227+
*/
228+
#ifndef CONFIG_SETTINGS_ZMS_NO_LL_DELETE
229+
/* Otherwise, Settings item is not stored correctly in the ZMS.
230+
* ZMS entry for its name or value is either missing or deleted.
231+
* Clean dirty entries to make space for future settings item.
219232
*/
220233
ret = settings_zms_delete(cf, ZMS_NAME_HASH_ID(ll_hash_id));
221234
if (ret < 0) {
222235
return ret;
223236
}
237+
#endif /* CONFIG_SETTINGS_ZMS_NO_LL_DELETE */
238+
/* update next ll_hash_id */
239+
ret = zms_read(&cf->cf_zms, ll_hash_id, &settings_element,
240+
sizeof(struct settings_hash_linked_list));
241+
if (ret < 0) {
242+
return ret;
243+
}
244+
ll_hash_id = settings_element.next_hash;
224245
continue;
225246
}
226247

@@ -288,7 +309,7 @@ static int settings_zms_save(struct settings_store *cs, const char *name, const
288309
}
289310
#endif
290311

291-
/* Let's find out if there is no hash collisions in the storage */
312+
/* Let's find out if there are hash collisions in the storage */
292313
write_name = true;
293314
hash_collision = true;
294315

@@ -364,6 +385,17 @@ static int settings_zms_save(struct settings_store *cs, const char *name, const
364385
if (rc < 0) {
365386
return rc;
366387
}
388+
#ifdef CONFIG_SETTINGS_ZMS_NO_LL_DELETE
389+
/* verify that the ll_node doesn't exist otherwise do not update it */
390+
rc = zms_read(&cf->cf_zms, name_hash | 1, &settings_element,
391+
sizeof(struct settings_hash_linked_list));
392+
if (rc >= 0) {
393+
goto no_ll_update;
394+
} else if (rc != -ENOENT) {
395+
return rc;
396+
}
397+
/* else the LL node doesn't exist let's update it */
398+
#endif /* CONFIG_SETTINGS_ZMS_NO_LL_DELETE */
367399
/* write linked list structure element */
368400
settings_element.next_hash = 0;
369401
/* Verify first that the linked list last element is not broken.
@@ -393,7 +425,9 @@ static int settings_zms_save(struct settings_store *cs, const char *name, const
393425
cf->second_to_last_hash_id = cf->last_hash_id;
394426
cf->last_hash_id = name_hash | 1;
395427
}
396-
428+
#ifdef CONFIG_SETTINGS_ZMS_NO_LL_DELETE
429+
no_ll_update:
430+
#endif /* CONFIG_SETTINGS_ZMS_NO_LL_DELETE */
397431
#if CONFIG_SETTINGS_ZMS_NAME_CACHE
398432
if (!name_in_cache) {
399433
settings_zms_cache_add(cf, name_hash & ZMS_HASH_MASK,

0 commit comments

Comments
 (0)