Skip to content

Commit 9a17999

Browse files
committed
[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 7d9d3fddea0a3ff999934c7aad99e54b2a8a864c)
1 parent b83478a commit 9a17999

File tree

7 files changed

+2155
-0
lines changed

7 files changed

+2155
-0
lines changed

include/zephyr/fs/zms.h

Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
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+
#if CONFIG_ZMS_LOOKUP_CACHE
66+
uint64_t lookup_cache[CONFIG_ZMS_LOOKUP_CACHE_SIZE];
67+
#endif
68+
};
69+
70+
/**
71+
* @}
72+
*/
73+
74+
/**
75+
* @brief Zephyr Memory Storage APIs
76+
* @defgroup zms_high_level_api Zephyr Memory Storage APIs
77+
* @ingroup zms
78+
* @{
79+
*/
80+
81+
/**
82+
* @brief Mount a ZMS file system onto the device specified in @p fs.
83+
*
84+
* @param fs Pointer to file system
85+
* @retval 0 Success
86+
* @retval -ERRNO errno code if error
87+
*/
88+
int zms_mount(struct zms_fs *fs);
89+
90+
/**
91+
* @brief Clear the ZMS file system from device.
92+
*
93+
* @param fs Pointer to file system
94+
* @retval 0 Success
95+
* @retval -ERRNO errno code if error
96+
*/
97+
int zms_clear(struct zms_fs *fs);
98+
99+
/**
100+
* @brief Write an entry to the file system.
101+
*
102+
* @note When @p len parameter is equal to @p 0 then entry is effectively removed (it is
103+
* equivalent to calling of zms_delete). It is not possible to distinguish between a deleted
104+
* entry and an entry with data of length 0.
105+
*
106+
* @param fs Pointer to file system
107+
* @param id Id of the entry to be written
108+
* @param data Pointer to the data to be written
109+
* @param len Number of bytes to be written (maximum 64 KB)
110+
*
111+
* @return Number of bytes written. On success, it will be equal to the number of bytes requested
112+
* to be written. When a rewrite of the same data already stored is attempted, nothing is written
113+
* to flash, thus 0 is returned. On error, returns negative value of errno.h defined error codes.
114+
*/
115+
ssize_t zms_write(struct zms_fs *fs, uint32_t id, const void *data, size_t len);
116+
117+
/**
118+
* @brief Delete an entry from the file system
119+
*
120+
* @param fs Pointer to file system
121+
* @param id Id of the entry to be deleted
122+
* @retval 0 Success
123+
* @retval -ERRNO errno code if error
124+
*/
125+
int zms_delete(struct zms_fs *fs, uint32_t id);
126+
127+
/**
128+
* @brief Read an entry from the file system.
129+
*
130+
* @param fs Pointer to file system
131+
* @param id Id of the entry to be read
132+
* @param data Pointer to data buffer
133+
* @param len Number of bytes to be read (or size of the allocated read buffer)
134+
*
135+
* @return Number of bytes read. On success, it will be equal to the number of bytes requested
136+
* to be read. When the return value is less than the number of bytes requested to read this
137+
* indicates that ATE contain less data than requested. On error, returns negative value of
138+
* errno.h defined error codes.
139+
*/
140+
ssize_t zms_read(struct zms_fs *fs, uint32_t id, void *data, size_t len);
141+
142+
/**
143+
* @brief Read a history entry from the file system.
144+
*
145+
* @param fs Pointer to file system
146+
* @param id Id of the entry to be read
147+
* @param data Pointer to data buffer
148+
* @param len Number of bytes to be read
149+
* @param cnt History counter: 0: latest entry, 1: one before latest ...
150+
*
151+
* @return Number of bytes read. On success, it will be equal to the number of bytes requested
152+
* to be read. When the return value is larger than the number of bytes requested to read this
153+
* indicates not all bytes were read, and more data is available. On error, returns negative
154+
* value of errno.h defined error codes.
155+
*/
156+
ssize_t zms_read_hist(struct zms_fs *fs, uint32_t id, void *data, size_t len, uint32_t cnt);
157+
158+
/**
159+
* @brief Gets the data size that is stored in an entry with a given id
160+
*
161+
* @param fs Pointer to file system
162+
* @param id Id of the entry that we want to get its data length
163+
*
164+
* @return Data length contained in the ATE. On success, it will be equal to the number of bytes
165+
* in the ATE. On error, returns negative value of errno.h defined error codes.
166+
*/
167+
ssize_t zms_get_data_length(struct zms_fs *fs, uint32_t id);
168+
/**
169+
* @brief Calculate the available free space in the file system.
170+
*
171+
* @param fs Pointer to file system
172+
*
173+
* @return Number of bytes free. On success, it will be equal to the number of bytes that can
174+
* still be written to the file system.
175+
* Calculating the free space is a time consuming operation, especially on spi flash.
176+
* On error, returns negative value of errno.h defined error codes.
177+
*/
178+
ssize_t zms_calc_free_space(struct zms_fs *fs);
179+
180+
/**
181+
* @brief Tell how many contiguous free space remains in the currently active ZMS sector.
182+
*
183+
* @param fs Pointer to the file system.
184+
*
185+
* @return Number of free bytes.
186+
*/
187+
size_t zms_sector_max_data_size(struct zms_fs *fs);
188+
189+
/**
190+
* @brief Close the currently active sector and switch to the next one.
191+
*
192+
* @note The garbage collector is called on the new sector.
193+
*
194+
* @warning This routine is made available for specific use cases.
195+
* It collides with the ZMS goal of avoiding any unnecessary flash erase operations.
196+
* Using this routine extensively can result in premature failure of the flash device.
197+
*
198+
* @param fs Pointer to the file system.
199+
*
200+
* @return 0 on success. On error, returns negative value of errno.h defined error codes.
201+
*/
202+
int zms_sector_use_next(struct zms_fs *fs);
203+
204+
/**
205+
* @}
206+
*/
207+
208+
#ifdef __cplusplus
209+
}
210+
#endif
211+
212+
#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)