diff --git a/include/fs/littlefs.h b/include/fs/littlefs.h index 131534f64f7..39a74e4b77b 100644 --- a/include/fs/littlefs.h +++ b/include/fs/littlefs.h @@ -57,7 +57,7 @@ struct fs_littlefs { * values are consistent with littlefs requirements. * * @note If you use a non-default configuration for cache size, you - * must also select @option{CONFIG_FS_LITTLEFS_FC_MEM_POOL} to relax + * must also select @option{CONFIG_FS_LITTLEFS_FC_HEAP_SIZE} to relax * the size constraints on per-file cache allocations. * * @param name the name for the structure. The defined object has diff --git a/subsys/fs/Kconfig.littlefs b/subsys/fs/Kconfig.littlefs index b1fb90ad810..dfd992a1d6f 100644 --- a/subsys/fs/Kconfig.littlefs +++ b/subsys/fs/Kconfig.littlefs @@ -69,7 +69,7 @@ config FS_LITTLEFS_BLOCK_CYCLES disable leveling. menuconfig FS_LITTLEFS_FC_MEM_POOL - bool "Enable flexible file cache sizes for littlefs" + bool "Enable flexible file cache sizes for littlefs (DEPRECATED)" help littlefs requires a per-file buffer to cache data. For applications that use the default configuration parameters a @@ -80,25 +80,75 @@ menuconfig FS_LITTLEFS_FC_MEM_POOL support different cache sizes for different partitions this preallocation is inadequate. - Select this feature to enable a memory pool allocator for - littlefs file caches. + This API is no longer approprate as the underlying storage solution + has been deprecated. Instead use FS_LITTLEFS_FC_HEAP_SIZE to + configure the size of a heap used to allocate caches for open files. +# This option deprecated in 2.5.0 if FS_LITTLEFS_FC_MEM_POOL config FS_LITTLEFS_FC_MEM_POOL_MIN_SIZE - int "Minimum block size for littlefs file cache memory pool" + int "(DEPRECATED)" default 16 + help + This API is no longer approprate as the underlying storage + solution has been deprecated. Instead use + FS_LITTLEFS_FC_HEAP to configure the size of a heap used to + allocate caches for open files. config FS_LITTLEFS_FC_MEM_POOL_MAX_SIZE - int "Maximum block size for littlefs file cache memory pool" + int "Block size for littlefs file cache heap (DEPRECATED)" default 1024 + help + A heap for file cache data is sized so that + FS_LITTLEFS_FC_MEM_POOL_NUM_BLOCKS allocations of size + FS_LITTLEFS_MEM_POOL_MAX_SIZE can be active simultaneously. + + This option configures the size. + + This API is no longer approprate as the underlying storage solution + has been deprecated. Instead use FS_LITTLEFS_FC_HEAP to configure + the size of a heap used to allocate caches for open files. config FS_LITTLEFS_FC_MEM_POOL_NUM_BLOCKS - int "Number of maximum sized blocks in littlefs file cache memory pool" + int "Number of maximum sized blocks in littlefs file cache heap (DEPRECATED)" default 2 + help + A heap for file cache data is sized so that + FS_LITTLEFS_FC_MEM_POOL_NUM_BLOCKS allocations of size + FS_LITTLEFS_MEM_POOL_MAX_SIZE can be active simultaneously. + + This option configures the total heap size based on the + block size. + + This API is no longer approprate as the underlying storage solution + has been deprecated. Instead use FS_LITTLEFS_FC_HEAP to configure + the size of a heap used to allocate caches for open files. endif # FS_LITTLEFS_FC_MEM_POOL -endmenu +endmenu # FS_LITTLEFS_FC_MEM_POOL + +config FS_LITTLEFS_FC_HEAP_SIZE + int "Enable flexible file cache sizes for littlefs" + default 0 + help + littlefs requires a per-file buffer to cache data. + + When applications customize littlefs configurations and support + different cache sizes for different partitions this preallocation is + inadequate as an application might require a small number of files + using a large cache size and a larger number of files using a + smaller cache size. In that case application should provide a + positive value for the heap size. Be aware that there is a + per-allocation overhead that affects how much usable space is + present in the heap. + + If this option is set to a non-positive value the heap is sized to + support up to FS_LITTLE_FS_NUM_FILES blocks of + FS_LITTLEFS_CACHE_SIZE bytes. Until FS_LITTLEFS_FC_MEM_POOL is + removed presence of that option changes the default to support + FS_LITTLEFS_FC_MEM_POOL_NUM_BLOCKS allocations of size + FS_LITTLEFS_MEM_POOL_MAX_SIZE endif # FILE_SYSTEM_LITTLEFS diff --git a/subsys/fs/littlefs_fs.c b/subsys/fs/littlefs_fs.c index 4d4839fb606..7ce176ac63a 100644 --- a/subsys/fs/littlefs_fs.c +++ b/subsys/fs/littlefs_fs.c @@ -32,24 +32,78 @@ struct lfs_file_data { #define LFS_FILEP(fp) (&((struct lfs_file_data *)(fp->filep))->file) /* Global memory pool for open files and dirs */ -K_MEM_SLAB_DEFINE(file_data_pool, sizeof(struct lfs_file_data), - CONFIG_FS_LITTLEFS_NUM_FILES, 4); -K_MEM_SLAB_DEFINE(lfs_dir_pool, sizeof(struct lfs_dir), - CONFIG_FS_LITTLEFS_NUM_DIRS, 4); +static K_MEM_SLAB_DEFINE(file_data_pool, sizeof(struct lfs_file_data), + CONFIG_FS_LITTLEFS_NUM_FILES, 4); +static K_MEM_SLAB_DEFINE(lfs_dir_pool, sizeof(struct lfs_dir), + CONFIG_FS_LITTLEFS_NUM_DIRS, 4); + +/* If either filecache memory pool is customized by either the legacy + * mem_pool or heap Kconfig options then we need to use a heap. + * Otherwise we can use a fixed region. + */ +#define FC_ON_HEAP defined(CONFIG_FS_LITTLEFS_FC_MEM_POOL) \ + || ((CONFIG_FS_LITTLEFS_FC_HEAP_SIZE - 0) > 0) + +#if FC_ON_HEAP + +/* Inferred overhead, in bytes, for each k_heap_aligned allocation for + * the filecache heap. This relates to the CHUNK_UNIT parameter in + * the heap implementation, but that value is not visible outside the + * kernel. + */ +#define FC_HEAP_PER_ALLOC_OVERHEAD 24U /* If not explicitly customizing provide a default that's appropriate * based on other configuration options. */ #ifndef CONFIG_FS_LITTLEFS_FC_MEM_POOL -BUILD_ASSERT(CONFIG_FS_LITTLEFS_CACHE_SIZE >= 4); -#define CONFIG_FS_LITTLEFS_FC_MEM_POOL_MIN_SIZE 4 #define CONFIG_FS_LITTLEFS_FC_MEM_POOL_MAX_SIZE CONFIG_FS_LITTLEFS_CACHE_SIZE #define CONFIG_FS_LITTLEFS_FC_MEM_POOL_NUM_BLOCKS CONFIG_FS_LITTLEFS_NUM_FILES #endif -K_HEAP_DEFINE(file_cache_pool, - CONFIG_FS_LITTLEFS_FC_MEM_POOL_MAX_SIZE * - CONFIG_FS_LITTLEFS_FC_MEM_POOL_NUM_BLOCKS); +/* If not explicitly customizing infer a default from the legacy + * mem-pool configuration options. + */ +#if (CONFIG_FS_LITTLEFS_FC_HEAP_SIZE - 0) <= 0 +#undef CONFIG_FS_LITTLEFS_FC_HEAP_SIZE +#define CONFIG_FS_LITTLEFS_FC_HEAP_SIZE \ + ((CONFIG_FS_LITTLEFS_FC_MEM_POOL_MAX_SIZE \ + + FC_HEAP_PER_ALLOC_OVERHEAD) \ + * CONFIG_FS_LITTLEFS_FC_MEM_POOL_NUM_BLOCKS) +#endif /* CONFIG_FS_LITTLEFS_FC_HEAP_SIZE */ + +static K_HEAP_DEFINE(file_cache_heap, CONFIG_FS_LITTLEFS_FC_HEAP_SIZE); + +#else /* FC_ON_HEAP */ + +static K_MEM_SLAB_DEFINE(file_cache_slab, CONFIG_FS_LITTLEFS_CACHE_SIZE, + CONFIG_FS_LITTLEFS_NUM_FILES, 4); + +#endif /* FC_ON_HEAP */ + +static inline void *fc_allocate(size_t size) +{ + void *ret = NULL; + +#if FC_ON_HEAP + ret = k_heap_alloc(&file_cache_heap, size, K_NO_WAIT); +#else + if (k_mem_slab_alloc(&file_cache_slab, &ret, K_NO_WAIT) != 0) { + ret = NULL; + } +#endif + + return ret; +} + +static inline void fc_release(void *buf) +{ +#if FC_ON_HEAP + k_heap_free(&file_cache_heap, buf); +#else /* FC_ON_HEAP */ + k_mem_slab_free(&file_cache_slab, &buf); +#endif /* FC_ON_HEAP */ +} static inline void fs_lock(struct fs_littlefs *fs) { @@ -174,7 +228,7 @@ static void release_file_data(struct fs_file_t *fp) struct lfs_file_data *fdp = fp->filep; if (fdp->config.buffer) { - k_heap_free(&file_cache_pool, fdp->cache_block); + fc_release(fdp->cache_block); } k_mem_slab_free(&file_data_pool, &fp->filep); @@ -212,8 +266,7 @@ static int littlefs_open(struct fs_file_t *fp, const char *path, memset(fdp, 0, sizeof(*fdp)); - fdp->cache_block = k_heap_alloc(&file_cache_pool, - lfs->cfg->cache_size, K_NO_WAIT); + fdp->cache_block = fc_allocate(lfs->cfg->cache_size); if (fdp->cache_block == NULL) { ret = -ENOMEM; goto out;