Skip to content

Commit 8df937e

Browse files
57300cfriedt
authored andcommitted
doc: storage: zms: Update to reflect new additions
The ATE structure section is now divided into subsections describing multiple ATE formats, including the one added for CONFIG_ZMS_ID_64BIT. The sections about features and recommendations are updated as well. Mentions of 32-bit key/ID are revised to account for 64-bit ID support. Mentions of <= 8 bytes data size also had to be reworked, because this property is tied to the chosen ATE format. Some unrelated, minor changes are also sprinkled throughout. Signed-off-by: Grzegorz Swiderski <[email protected]>
1 parent 4a3b87b commit 8df937e

File tree

1 file changed

+81
-26
lines changed

1 file changed

+81
-26
lines changed

doc/services/storage/zms/zms.rst

Lines changed: 81 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@
22

33
Zephyr Memory Storage (ZMS)
44
###########################
5+
56
Zephyr Memory Storage is a new key-value storage system that is designed to work with all types
67
of non-volatile storage technologies. It supports classical on-chip NOR flash as well as new
78
technologies like RRAM and MRAM that do not require a separate erase operation at all, that is,
89
data on these types of devices can be overwritten directly at any time.
910

1011
General behavior
1112
****************
13+
1214
ZMS divides the memory space into sectors (minimum 2), and each sector is filled with key-value
1315
pairs until it is full.
1416

@@ -32,6 +34,7 @@ the first sector after garbage collecting it and erasing its content.
3234

3335
Composition of a sector
3436
=======================
37+
3538
A sector is organized in this form (example with 3 sectors):
3639

3740
.. list-table::
@@ -88,7 +91,7 @@ Definition of each element in the sector
8891
``GC_done ATE`` is written to indicate that the next sector has already been garbage-collected.
8992
This ATE could be at any position of the sector.
9093

91-
``ID ATE`` are entries that contain a 32-bit key and describe where the data is stored, its
94+
``ID ATE`` contains a key of type :c:type:`zms_id_t` and describes where the data is stored, its
9295
size and its CRC32.
9396

9497
``Data`` is the actual value associated to the ID-ATE.
@@ -103,7 +106,7 @@ Mounting the storage system starts by getting the flash parameters, checking tha
103106
properties are correct (sector_size, sector_count ...) then calling the zms_init function to
104107
make the storage ready.
105108

106-
To mount the filesystem the following elements in the ``zms_fs`` structure must be initialized:
109+
To mount the filesystem the following elements in the :c:struct:`zms_fs` structure must be initialized:
107110

108111
.. code-block:: c
109112
@@ -132,15 +135,14 @@ It must look for a closed sector followed by an open one, then within the open s
132135
After that, it checks that the sector after this one is empty, or it will erase it.
133136

134137
ZMS ID/data write
135-
===================
138+
=================
136139

137140
To avoid rewriting the same data with the same ID again, ZMS must look in all the sectors if the
138141
same ID exists and then compares its data. If the data is identical, no write is performed.
139142
If it must perform a write, then an ATE and the data (if the operation is not a delete) are written
140143
in the sector.
141144
If the sector is full (cannot hold the current data + ATE), ZMS has to move to the next sector,
142145
garbage collect the sector after the newly opened one then erase it.
143-
Data whose size is smaller or equal to 8 bytes are written within the ATE.
144146

145147
ZMS ID/data read (with history)
146148
===============================
@@ -162,7 +164,7 @@ could slow down the calling thread.
162164
The cycle counter
163165
=================
164166

165-
Each sector has a lead cycle counter which is a ``uin8_t`` that is used to validate all the other
167+
Each sector has a lead cycle counter which is a ``uint8_t`` that is used to validate all the other
166168
ATEs.
167169
The lead cycle counter is stored in the empty ATE.
168170
To become valid, an ATE must have the same cycle counter as the one stored in the empty ATE.
@@ -196,16 +198,52 @@ This will guarantee the application that the next write won't trigger the garbag
196198
ATE (Allocation Table Entry) structure
197199
======================================
198200

199-
An entry has 16 bytes divided between these fields:
201+
An entry uses 16 bytes to encode its information.
202+
The exact structure is determined by ATE format which can be selected for a given application.
203+
204+
ZMS defines multiple ATE formats tailored for different feature sets. At runtime, it recognizes
205+
the format using the metadata field in empty ATEs, which has the same byte position in all formats.
200206

201-
See the :c:struct:`zms_ate` structure.
207+
.. table:: Entry format for 32-bit IDs
208+
209+
+-----+----------+--+--+--+--+--+--+--+--+---+---+---+---+---+---+
210+
| 0 | 1 | 2| 3| 4| 5| 6| 7| 8| 9| 10| 11| 12| 13| 14| 15|
211+
+=====+==========+==+==+==+==+==+==+==+==+===+===+===+===+===+===+
212+
| | | | | data (if len <= 8) |
213+
| | | | +-------------+---------------+
214+
| crc8| cycle_cnt| len | id | | data_crc |
215+
| | | | | offset +---------------+
216+
| | | | | | metadata |
217+
+-----+----------+-----+-----------+-------------+---------------+
218+
219+
This is the default format which is captured in the API documentation for :c:struct:`zms_ate`.
220+
The ``data_crc`` is optionally included to integrity-check data stored at the top of the sector.
202221

203222
.. note:: The CRC of the data is checked only when a full read of the data is made.
204223
The CRC of the data is not checked for a partial read, as it is computed for the whole element.
205224

206225
.. warning:: Enabling the CRC feature on previously existing ZMS content that did not have it
207226
enabled will make all existing data invalid.
208227

228+
.. table:: Entry format for 64-bit IDs
229+
230+
+-----+----------+--+--+--+--+--+--+--+--+---+---+----+----+----+----+
231+
| 0 | 1 | 2| 3| 4| 5| 6| 7| 8| 9| 10| 11| 12 | 13 | 14 | 15 |
232+
+=====+==========+==+==+==+==+==+==+==+==+===+===+====+====+====+====+
233+
| | | | | data (if len <= 4)|
234+
| | | | +-------------------+
235+
| crc8| cycle_cnt| len | id | offset |
236+
| | | | +-------------------+
237+
| | | | | metadata |
238+
+-----+----------+-----+-------------------------+-------------------+
239+
240+
This format is selected when :kconfig:option:`CONFIG_ZMS_ID_64BIT` is enabled.
241+
242+
.. warning:: Selecting a different ATE format than the one used by previously existing ZMS content
243+
will make all existing data invalid.
244+
245+
.. note:: The ZMS backend for :ref:`Settings <settings_api>` does not support this format.
246+
209247
Available space for user data (key-value pairs)
210248
***********************************************
211249

@@ -220,8 +258,11 @@ The empty sector will rotate between the 4 sectors in the partition.
220258
Small data values
221259
=================
222260

223-
Values smaller than or equal to 8 bytes will be stored within the entry (ATE) itself, without
261+
Values which are sufficiently small will be stored within the entry (ATE) itself, without
224262
writing data at the top of the sector.
263+
The amount of data that can fit inside the entry depends on its selected format.
264+
See the `ATE structure <#ate-allocation-table-entry-structure>`_ section.
265+
225266
ZMS has an entry size of 16 bytes which means that the maximum available space in a partition to
226267
store data is computed in this scenario as:
227268

@@ -239,24 +280,25 @@ Where:
239280

240281
``(5 * ATE_SIZE)``: Reserved ATEs for header and delete items
241282

242-
``DATA_SIZE``: Size of the small data values (range from 1 to 8)
283+
``DATA_SIZE``: 8 bytes or 4 bytes depending on the ATE format
243284

244-
For example for 4 sectors of 1024 bytes, free space for 8-byte length data is :math:`\frac{3 \times 944 \times 8}{16} = 1416 \, \text{ bytes}`.
285+
For example for 4 sectors of 1024 bytes, with the default ATE format, free space for 8-byte length
286+
data is :math:`\frac{3 \times 944 \times 8}{16} = 1416 \, \text{ bytes}`.
245287

246288
Large data values
247289
=================
248290

249-
Large data values ( > 8 bytes) are stored separately at the top of the sector.
291+
Values exceeding ``DATA_SIZE`` are stored outside of the ATE at the top of the sector.
250292
In this case, it is hard to estimate the free available space, as this depends on the size of
251-
the data. But we can take into account that for N bytes of data (N > 8 bytes) an additional
252-
16 bytes of ATE must be added at the bottom of the sector.
293+
the data. But we can take into account that for N bytes of data added at the top of the sector,
294+
an additional 16 bytes of ATE must be added at the bottom of the sector, which adds up to
295+
:math:`N + 16` bytes for the key-value pair.
253296

254297
Let's take an example:
255298

256299
For a partition that has 4 sectors of 1024 bytes and for data size of 64 bytes.
257-
Only 3 sectors are available for writes with a capacity of 944 bytes each.
258-
Each key-value pair needs an extra 16 bytes for the ATE, which makes it possible to store 11 pairs
259-
in each sector (:math:`\frac{944}{80}`).
300+
Only 3 sectors are available for writes with a capacity of 944 bytes each,
301+
which makes it possible to store 11 key-value pairs in each sector (:math:`\frac{944}{64 + 16}`).
260302
Total data that could be stored in this partition for this case is :math:`11 \times 3 \times 64 = 2112 \text{ bytes}`.
261303

262304
Wear leveling
@@ -292,7 +334,7 @@ memory cells cannot be overwritten), and for storage devices that do not require
292334
operation, memory cells can be overwritten directly.
293335

294336
A typical scenario is shown here to calculate the life expectancy of a device:
295-
Let's suppose that we store an 8-byte variable using the same ID but its content changes every
337+
Let's suppose that we store a 4-byte variable using the same ID but its content changes every
296338
minute. The partition has 4 sectors with 1024 bytes each.
297339
Each write of the variable requires 16 bytes of storage.
298340
As we have 944 bytes available for ATEs for each sector, and because ZMS is a fast-forward
@@ -308,8 +350,8 @@ For storage devices that can be written 20 000 times, the storage will last abou
308350

309351
To make a more general formula we must first compute the effective used size in ZMS by our
310352
typical set of data.
311-
For ID/data pairs with data <= 8 bytes, ``effective_size`` is 16 bytes.
312-
For ID/data pairs with data > 8 bytes, ``effective_size`` is ``16 + sizeof(data)`` bytes.
353+
For ID/data pairs with `small data <#small-data-values>`_, ``effective_size`` is ``16`` bytes,
354+
while for `large data <#large-data-values>`_, ``effective_size`` is ``16 + sizeof(data)`` bytes.
313355
Let's suppose that ``total_effective_size`` is the total size of the data that is written in
314356
the storage and that the partition is sized appropriately (double of the effective size) to avoid
315357
having the garbage collector moving blocks all the time.
@@ -334,28 +376,32 @@ Where:
334376

335377
Features
336378
********
379+
337380
ZMS has introduced many features compared to existing storage system like NVS and will evolve
338381
from its initial version to include more features that satisfies new technologies requirements
339382
such as low latency and bigger storage space.
340383

341384
Existing features
342385
=================
386+
343387
Version 1
344388
---------
389+
345390
- Supports storage devices that do not require an erase operation (only one write operation
346391
to invalidate a sector)
347392
- Supports large partition and sector sizes (64-bit address space)
348-
- Supports 32-bit IDs
349-
- Small-sized data (<= 8 bytes) are stored in the ATE itself
393+
- Supports 32-bit IDs and 64-bit IDs
394+
- Small data values are stored in the ATE itself
350395
- Built-in data CRC32 (included in the ATE)
351396
- Versioning of ZMS (to handle future evolutions)
352397
- Supports large ``write-block-size`` (only for platforms that need it)
398+
- Supports multiple ATE formats to satisfy the requirements of different applications
353399

354400
Future features
355401
===============
356402

357-
- Add multiple format ATE support to be able to use ZMS with different ATE formats that satisfies
358-
requirements from application
403+
- Add the possibility to mount multiple filesystems with different ATE formats
404+
(currently, all filesystems in the same application must use the same format)
359405
- Add the possibility to skip garbage collector for some application usage where ID/value pairs
360406
are written periodically and do not exceed half of the partition size (there is always an old
361407
entry with the same ID).
@@ -369,6 +415,7 @@ Future features
369415

370416
ZMS and other storage systems in Zephyr
371417
=======================================
418+
372419
This section describes ZMS in the wider context of storage systems in Zephyr (not full filesystems,
373420
but simpler, non-hierarchical ones).
374421
Today Zephyr includes at least two other systems that are somewhat comparable in scope and
@@ -386,8 +433,8 @@ and this section provides information to help make a choice.
386433
ATEs and smaller header ATEs). Erasing flash in NVS is also very fast and do not require an
387434
additional write operation compared to ZMS.
388435
For these devices, NVS reads/writes will be faster as well than ZMS as it has smaller ATE size.
389-
- If your application needs more than 64K IDs for storage, :ref:`ZMS <zms_api>` is recommended here as it
390-
has a 32-bit ID field.
436+
- If your application needs more than 64K IDs for storage, :ref:`ZMS <zms_api>` is recommended here
437+
because the ID field is up to 64-bit.
391438
- If your application is working in a FIFO mode (First-in First-out) then :ref:`FCB <fcb_api>` is
392439
the best storage solution for this use case.
393440

@@ -417,7 +464,7 @@ Sector size and count
417464
- For some subsystems like :ref:`Settings <settings_api>`, all path-value pairs are split into two ZMS entries (ATEs).
418465
The headers needed by the two entries should be accounted for when computing the needed storage
419466
space.
420-
- Storing small data (<= 8 bytes) in ZMS entries can increase the performance, as this data is
467+
- Using `small data values <#small-data-values>`_ can increase the performance, as this data is
421468
written within the entry.
422469
For example, for the :ref:`Settings <settings_api>` subsystem, choosing a path name that is
423470
less than or equal to 8 bytes can make reads and writes faster.
@@ -433,6 +480,14 @@ Cache size
433480
divided into two ZMS entries. The recommendation for the cache size is to make it at least
434481
twice the number of Settings entries.
435482

483+
ID size
484+
=======
485+
486+
- The 64-bit ID space is expected to be larger than necessary for most applications.
487+
Unless you have a particular need for this, it's recommended to stick with 32-bit IDs.
488+
This is expected to have a slight impact on code size and performance, even on 64-bit systems,
489+
because the byte position of IDs in storage is not aligned to an 8-byte boundary.
490+
436491
API Reference
437492
*************
438493

0 commit comments

Comments
 (0)