Skip to content

Commit 14c65e3

Browse files
rghaddabrlubos
authored andcommitted
[nrf fromlist] fs: introduce ZMS a new Memory storage system
ZMS is the abreviation of Zephyr Memory Storage. It is a storage developed to target especially the non erasable devices. The new memory storage system inherit from the NVS storage multiple features and introduce new ones : * Inherited features : - light key-value based storage - cache for entries - Wear Leveling of flash memory - Resilience to power failures * New features : - cycle counter for non erasable devices (instead of erase emulation) - Keys up to 32-bit - Built-in support of CRC32 for data - Small size data (<= 8 bytes) integrated within entries Upstream PR: zephyrproject-rtos/zephyr#77930 Signed-off-by: Riadh Ghaddab <[email protected]> (cherry picked from commit 0feaf588f9628e4279001eb390ac07ae1e818f9e)
1 parent 1a605b0 commit 14c65e3

File tree

7 files changed

+2111
-0
lines changed

7 files changed

+2111
-0
lines changed

include/zephyr/fs/zms.h

Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
/* ZMS: Zephyr Memory Storage
2+
*
3+
* Copyright (c) 2024 BayLibre SAS
4+
*
5+
* SPDX-License-Identifier: Apache-2.0
6+
*/
7+
#ifndef ZEPHYR_INCLUDE_FS_ZMS_H_
8+
#define ZEPHYR_INCLUDE_FS_ZMS_H_
9+
10+
#include <zephyr/drivers/flash.h>
11+
#include <sys/types.h>
12+
#include <zephyr/kernel.h>
13+
#include <zephyr/device.h>
14+
#include <zephyr/toolchain.h>
15+
16+
#ifdef __cplusplus
17+
extern "C" {
18+
#endif
19+
20+
/**
21+
* @brief Zephyr Memory Storage (ZMS)
22+
* @defgroup zms Zephyr Memory Storage (ZMS)
23+
* @ingroup file_system_storage
24+
* @{
25+
* @}
26+
*/
27+
28+
/**
29+
* @brief Zephyr Memory Storage Data Structures
30+
* @defgroup zms_data_structures Zephyr Memory Storage Data Structures
31+
* @ingroup zms
32+
* @{
33+
*/
34+
35+
/**
36+
* @brief Zephyr Memory Storage File system structure
37+
*/
38+
struct zms_fs {
39+
/** File system offset in flash **/
40+
off_t offset;
41+
/** Allocation table entry write address.
42+
* Addresses are stored as uint64_t:
43+
* - high 4 bytes correspond to the sector
44+
* - low 4 bytes are the offset in the sector
45+
*/
46+
uint64_t ate_wra;
47+
/** Data write address */
48+
uint64_t data_wra;
49+
/** Storage system is split into sectors, each sector size must be multiple of erase-blocks
50+
* if the device has erase capabilities
51+
*/
52+
uint32_t sector_size;
53+
/** Number of sectors in the file system */
54+
uint32_t sector_count;
55+
/** Current cycle counter of the active sector (pointed by ate_wra)*/
56+
uint8_t sector_cycle;
57+
/** Flag indicating if the file system is initialized */
58+
bool ready;
59+
/** Mutex */
60+
struct k_mutex zms_lock;
61+
/** Flash device runtime structure */
62+
const struct device *flash_device;
63+
/** Flash memory parameters structure */
64+
const struct flash_parameters *flash_parameters;
65+
/** Size of an Allocation Table Entry */
66+
size_t ate_size;
67+
#if CONFIG_ZMS_LOOKUP_CACHE
68+
/** Lookup table used to cache ATE address of a written ID */
69+
uint64_t lookup_cache[CONFIG_ZMS_LOOKUP_CACHE_SIZE];
70+
#endif
71+
};
72+
73+
/**
74+
* @}
75+
*/
76+
77+
/**
78+
* @brief Zephyr Memory Storage APIs
79+
* @defgroup zms_high_level_api Zephyr Memory Storage APIs
80+
* @ingroup zms
81+
* @{
82+
*/
83+
84+
/**
85+
* @brief Mount a ZMS file system onto the device specified in @p fs.
86+
*
87+
* @param fs Pointer to file system
88+
* @retval 0 Success
89+
* @retval -ERRNO errno code if error
90+
*/
91+
int zms_mount(struct zms_fs *fs);
92+
93+
/**
94+
* @brief Clear the ZMS file system from device.
95+
*
96+
* @param fs Pointer to file system
97+
* @retval 0 Success
98+
* @retval -ERRNO errno code if error
99+
*/
100+
int zms_clear(struct zms_fs *fs);
101+
102+
/**
103+
* @brief Write an entry to the file system.
104+
*
105+
* @note When @p len parameter is equal to @p 0 then entry is effectively removed (it is
106+
* equivalent to calling of zms_delete). It is not possible to distinguish between a deleted
107+
* entry and an entry with data of length 0.
108+
*
109+
* @param fs Pointer to file system
110+
* @param id Id of the entry to be written
111+
* @param data Pointer to the data to be written
112+
* @param len Number of bytes to be written (maximum 64 KB)
113+
*
114+
* @return Number of bytes written. On success, it will be equal to the number of bytes requested
115+
* to be written. When a rewrite of the same data already stored is attempted, nothing is written
116+
* to flash, thus 0 is returned. On error, returns negative value of errno.h defined error codes.
117+
*/
118+
ssize_t zms_write(struct zms_fs *fs, uint32_t id, const void *data, size_t len);
119+
120+
/**
121+
* @brief Delete an entry from the file system
122+
*
123+
* @param fs Pointer to file system
124+
* @param id Id of the entry to be deleted
125+
* @retval 0 Success
126+
* @retval -ERRNO errno code if error
127+
*/
128+
int zms_delete(struct zms_fs *fs, uint32_t id);
129+
130+
/**
131+
* @brief Read an entry from the file system.
132+
*
133+
* @param fs Pointer to file system
134+
* @param id Id of the entry to be read
135+
* @param data Pointer to data buffer
136+
* @param len Number of bytes to be read (or size of the allocated read buffer)
137+
*
138+
* @return Number of bytes read. On success, it will be equal to the number of bytes requested
139+
* to be read. When the return value is less than the number of bytes requested to read this
140+
* indicates that ATE contain less data than requested. On error, returns negative value of
141+
* errno.h defined error codes.
142+
*/
143+
ssize_t zms_read(struct zms_fs *fs, uint32_t id, void *data, size_t len);
144+
145+
/**
146+
* @brief Read a history entry from the file system.
147+
*
148+
* @param fs Pointer to file system
149+
* @param id Id of the entry to be read
150+
* @param data Pointer to data buffer
151+
* @param len Number of bytes to be read
152+
* @param cnt History counter: 0: latest entry, 1: one before latest ...
153+
*
154+
* @return Number of bytes read. On success, it will be equal to the number of bytes requested
155+
* to be read. When the return value is larger than the number of bytes requested to read this
156+
* indicates not all bytes were read, and more data is available. On error, returns negative
157+
* value of errno.h defined error codes.
158+
*/
159+
ssize_t zms_read_hist(struct zms_fs *fs, uint32_t id, void *data, size_t len, uint32_t cnt);
160+
161+
/**
162+
* @brief Gets the data size that is stored in an entry with a given id
163+
*
164+
* @param fs Pointer to file system
165+
* @param id Id of the entry that we want to get its data length
166+
*
167+
* @return Data length contained in the ATE. On success, it will be equal to the number of bytes
168+
* in the ATE. On error, returns negative value of errno.h defined error codes.
169+
*/
170+
ssize_t zms_get_data_length(struct zms_fs *fs, uint32_t id);
171+
/**
172+
* @brief Calculate the available free space in the file system.
173+
*
174+
* @param fs Pointer to file system
175+
*
176+
* @return Number of bytes free. On success, it will be equal to the number of bytes that can
177+
* still be written to the file system.
178+
* Calculating the free space is a time consuming operation, especially on spi flash.
179+
* On error, returns negative value of errno.h defined error codes.
180+
*/
181+
ssize_t zms_calc_free_space(struct zms_fs *fs);
182+
183+
/**
184+
* @brief Tell how many contiguous free space remains in the currently active ZMS sector.
185+
*
186+
* @param fs Pointer to the file system.
187+
*
188+
* @return Number of free bytes.
189+
*/
190+
size_t zms_sector_max_data_size(struct zms_fs *fs);
191+
192+
/**
193+
* @brief Close the currently active sector and switch to the next one.
194+
*
195+
* @note The garbage collector is called on the new sector.
196+
*
197+
* @warning This routine is made available for specific use cases.
198+
* It collides with the ZMS goal of avoiding any unnecessary flash erase operations.
199+
* Using this routine extensively can result in premature failure of the flash device.
200+
*
201+
* @param fs Pointer to the file system.
202+
*
203+
* @return 0 on success. On error, returns negative value of errno.h defined error codes.
204+
*/
205+
int zms_sector_use_next(struct zms_fs *fs);
206+
207+
/**
208+
* @}
209+
*/
210+
211+
#ifdef __cplusplus
212+
}
213+
#endif
214+
215+
#endif /* ZEPHYR_INCLUDE_FS_ZMS_H_ */

subsys/fs/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ endif()
2525

2626
add_subdirectory_ifdef(CONFIG_FCB ./fcb)
2727
add_subdirectory_ifdef(CONFIG_NVS ./nvs)
28+
add_subdirectory_ifdef(CONFIG_ZMS ./zms)
2829

2930
if(CONFIG_FUSE_FS_ACCESS)
3031
zephyr_library_named(FS_FUSE)

subsys/fs/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,5 +99,6 @@ endif # FILE_SYSTEM
9999

100100
rsource "fcb/Kconfig"
101101
rsource "nvs/Kconfig"
102+
rsource "zms/Kconfig"
102103

103104
endmenu

subsys/fs/zms/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#SPDX-License-Identifier: Apache-2.0
2+
3+
zephyr_sources(zms.c)

subsys/fs/zms/Kconfig

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
#Zephyr Memory Storage ZMS
2+
3+
#Copyright (c) 2024 BayLibre SAS
4+
5+
#SPDX-License-Identifier: Apache-2.0
6+
7+
config ZMS
8+
bool "Zephyr Memory Storage"
9+
select CRC
10+
help
11+
Enable support of Zephyr Memory Storage.
12+
13+
if ZMS
14+
15+
config ZMS_LOOKUP_CACHE
16+
bool "ZMS lookup cache"
17+
help
18+
Enable ZMS cache to reduce the ZMS data lookup time.
19+
Each cache entry holds an address of the most recent allocation
20+
table entry (ATE) for all ZMS IDs that fall into that cache position.
21+
22+
config ZMS_LOOKUP_CACHE_SIZE
23+
int "ZMS Storage lookup cache size"
24+
default 128
25+
range 1 65536
26+
depends on ZMS_LOOKUP_CACHE
27+
help
28+
Number of entries in ZMS lookup cache.
29+
It is recommended that it should be a power of 2.
30+
Every additional entry in cache will add 8 bytes in RAM
31+
32+
config ZMS_DATA_CRC
33+
bool "ZMS DATA CRC"
34+
help
35+
Enables DATA CRC
36+
37+
config ZMS_CUSTOM_BLOCK_SIZE
38+
bool "Custom buffer size used by ZMS for reads and writes"
39+
default n
40+
help
41+
ZMS uses internal buffers to read/write and compare stored data.
42+
Increasing the size of these buffers should be done carefully in order to not
43+
overflow the stack.
44+
Increasing this buffer means as well that ZMS could work with storage devices
45+
that have larger write-block-size which decreases ZMS performance
46+
47+
config ZMS_MAX_BLOCK_SIZE
48+
int "ZMS internal buffer size"
49+
default 32
50+
depends on ZMS_CUSTOM_BLOCK_SIZE
51+
help
52+
Changes the internal buffer size of ZMS
53+
54+
module = ZMS
55+
module-str = zms
56+
source "subsys/logging/Kconfig.template.log_config"
57+
58+
endif # ZMS

0 commit comments

Comments
 (0)