fs: Implement mkfs operation in littleFS

Provide an implementation of fs_mkfs operation in littleFS.

Signed-off-by: Franciszek Zdobylak <fzdobylak@internships.antmicro.com>
This commit is contained in:
Franciszek Zdobylak 2022-10-24 08:36:59 +02:00 committed by Carles Cufí
commit 78f8937470

View file

@ -58,10 +58,10 @@ BUILD_ASSERT((CONFIG_FS_LITTLEFS_HEAP_PER_ALLOC_OVERHEAD_SIZE % 8) == 0);
static K_HEAP_DEFINE(file_cache_heap, CONFIG_FS_LITTLEFS_FC_HEAP_SIZE); static K_HEAP_DEFINE(file_cache_heap, CONFIG_FS_LITTLEFS_FC_HEAP_SIZE);
static inline bool littlefs_on_blkdev(struct fs_mount_t *mountp) static inline bool littlefs_on_blkdev(int flags)
{ {
return IS_ENABLED(CONFIG_FS_LITTLEFS_BLK_DEV) && return IS_ENABLED(CONFIG_FS_LITTLEFS_BLK_DEV) &&
mountp->flags & FS_MOUNT_FLAG_USE_DISK_ACCESS; flags & FS_MOUNT_FLAG_USE_DISK_ACCESS;
} }
static inline void *fc_allocate(size_t size) static inline void *fc_allocate(size_t size)
@ -619,10 +619,9 @@ static lfs_size_t get_block_size(const struct flash_area *fa)
return ctx.max_size; return ctx.max_size;
} }
static int littlefs_flash_init(struct fs_mount_t *mountp) static int littlefs_flash_init(struct fs_littlefs *fs, uintptr_t dev_id)
{ {
unsigned int area_id = (uintptr_t)mountp->storage_dev; unsigned int area_id = (uintptr_t)dev_id;
struct fs_littlefs *fs = mountp->fs_data;
const struct flash_area **fap = (const struct flash_area **)&fs->backend; const struct flash_area **fap = (const struct flash_area **)&fs->backend;
const struct device *dev; const struct device *dev;
int ret; int ret;
@ -648,37 +647,29 @@ static int littlefs_flash_init(struct fs_mount_t *mountp)
return 0; return 0;
} }
static int littlefs_mount(struct fs_mount_t *mountp) static int littlefs_init_backend(struct fs_littlefs *fs, uintptr_t dev_id, int flags)
{ {
int ret = 0; int ret = 0;
struct fs_littlefs *fs = mountp->fs_data;
bool block_dev = littlefs_on_blkdev(mountp);
LOG_INF("LittleFS version %u.%u, disk version %u.%u", if (littlefs_on_blkdev(flags)) {
LFS_VERSION_MAJOR, LFS_VERSION_MINOR, fs->backend = (void *) dev_id;
LFS_DISK_VERSION_MAJOR, LFS_DISK_VERSION_MINOR);
if (fs->backend) {
return -EBUSY;
}
/* Create and take mutex. */
k_mutex_init(&fs->mutex);
fs_lock(fs);
if (IS_ENABLED(CONFIG_FS_LITTLEFS_BLK_DEV) && block_dev) {
fs->backend = mountp->storage_dev;
ret = disk_access_init((char *) fs->backend); ret = disk_access_init((char *) fs->backend);
if (ret < 0) { if (ret < 0) {
LOG_ERR("Storage init ERROR!"); LOG_ERR("Storage init ERROR!");
goto out; return ret;
} }
} else { } else {
ret = littlefs_flash_init(mountp); ret = littlefs_flash_init(fs, dev_id);
if (ret < 0) { if (ret < 0) {
goto out; return ret;
} }
} }
return 0;
}
static int littlefs_init_cfg(struct fs_littlefs *fs, int flags)
{
int ret = 0;
BUILD_ASSERT(CONFIG_FS_LITTLEFS_READ_SIZE > 0); BUILD_ASSERT(CONFIG_FS_LITTLEFS_READ_SIZE > 0);
BUILD_ASSERT(CONFIG_FS_LITTLEFS_PROG_SIZE > 0); BUILD_ASSERT(CONFIG_FS_LITTLEFS_PROG_SIZE > 0);
@ -708,13 +699,13 @@ static int littlefs_mount(struct fs_mount_t *mountp)
lfs_size_t block_size = lcp->block_size; lfs_size_t block_size = lcp->block_size;
if (block_size == 0) { if (block_size == 0) {
if (IS_ENABLED(CONFIG_FS_LITTLEFS_BLK_DEV) && block_dev) { if (littlefs_on_blkdev(flags)) {
ret = disk_access_ioctl((char *) fs->backend, ret = disk_access_ioctl((char *) fs->backend,
DISK_IOCTL_GET_SECTOR_SIZE, DISK_IOCTL_GET_SECTOR_SIZE,
&block_size); &block_size);
if (ret < 0) { if (ret < 0) {
LOG_ERR("Unable to get sector size"); LOG_ERR("Unable to get sector size");
goto out; return ret;
} }
} else { } else {
block_size = get_block_size((struct flash_area *)fs->backend); block_size = get_block_size((struct flash_area *)fs->backend);
@ -723,8 +714,7 @@ static int littlefs_mount(struct fs_mount_t *mountp)
if (block_size == 0) { if (block_size == 0) {
__ASSERT_NO_MSG(block_size != 0); __ASSERT_NO_MSG(block_size != 0);
ret = -EINVAL; return -EINVAL;
goto out;
} }
int32_t block_cycles = lcp->block_cycles; int32_t block_cycles = lcp->block_cycles;
@ -752,14 +742,13 @@ static int littlefs_mount(struct fs_mount_t *mountp)
/* No, you don't get to override this. */ /* No, you don't get to override this. */
lfs_size_t block_count; lfs_size_t block_count;
if (IS_ENABLED(CONFIG_FS_LITTLEFS_BLK_DEV) && block_dev) { if (littlefs_on_blkdev(flags)) {
ret = disk_access_ioctl((char *) fs->backend, ret = disk_access_ioctl((char *) fs->backend,
DISK_IOCTL_GET_SECTOR_COUNT, DISK_IOCTL_GET_SECTOR_COUNT,
&block_count); &block_count);
if (ret < 0) { if (ret < 0) {
LOG_ERR("Unable to get sector count!"); LOG_ERR("Unable to get sector count!");
ret = -EINVAL; return -EINVAL;
goto out;
} }
LOG_INF("FS at %s: is %u 0x%x-byte blocks with %u cycle", LOG_INF("FS at %s: is %u 0x%x-byte blocks with %u cycle",
(char *) fs->backend, block_count, block_size, (char *) fs->backend, block_count, block_size,
@ -789,7 +778,7 @@ static int littlefs_mount(struct fs_mount_t *mountp)
lcp->context = fs->backend; lcp->context = fs->backend;
/* Set the validated/defaulted values. */ /* Set the validated/defaulted values. */
if (IS_ENABLED(CONFIG_FS_LITTLEFS_BLK_DEV) && block_dev) { if (littlefs_on_blkdev(flags)) {
lcp->read = lfs_api_read_blk; lcp->read = lfs_api_read_blk;
lcp->prog = lfs_api_prog_blk; lcp->prog = lfs_api_prog_blk;
lcp->erase = lfs_api_erase_blk; lcp->erase = lfs_api_erase_blk;
@ -821,6 +810,46 @@ static int littlefs_mount(struct fs_mount_t *mountp)
lcp->block_size = block_size; lcp->block_size = block_size;
lcp->block_count = block_count; lcp->block_count = block_count;
lcp->block_cycles = block_cycles; lcp->block_cycles = block_cycles;
return 0;
}
static int littlefs_init_fs(struct fs_littlefs *fs, int dev_id, int flags)
{
int ret = 0;
LOG_INF("LittleFS version %u.%u, disk version %u.%u",
LFS_VERSION_MAJOR, LFS_VERSION_MINOR,
LFS_DISK_VERSION_MAJOR, LFS_DISK_VERSION_MINOR);
if (fs->backend) {
return -EBUSY;
}
ret = littlefs_init_backend(fs, dev_id, flags);
if (ret < 0) {
return ret;
}
ret = littlefs_init_cfg(fs, flags);
if (ret < 0) {
return ret;
}
return 0;
}
static int littlefs_mount(struct fs_mount_t *mountp)
{
int ret = 0;
struct fs_littlefs *fs = mountp->fs_data;
/* Create and take mutex. */
k_mutex_init(&fs->mutex);
fs_lock(fs);
ret = littlefs_init_fs(fs, (uintptr_t)mountp->storage_dev, mountp->flags);
if (ret < 0) {
goto out;
}
/* Mount it, formatting if needed. */ /* Mount it, formatting if needed. */
ret = lfs_mount(&fs->lfs, &fs->cfg); ret = lfs_mount(&fs->lfs, &fs->cfg);
@ -860,6 +889,44 @@ out:
return ret; return ret;
} }
#if defined(CONFIG_FILE_SYSTEM_MKFS)
FS_LITTLEFS_DECLARE_DEFAULT_CONFIG(fs_cfg);
static int littlefs_mkfs(uintptr_t dev_id, void *cfg, int flags)
{
int ret = 0;
struct fs_littlefs *fs = &fs_cfg;
if (cfg != NULL) {
fs = (struct fs_littlefs *)cfg;
}
fs->backend = NULL;
/* Create and take mutex. */
k_mutex_init(&fs->mutex);
fs_lock(fs);
ret = littlefs_init_fs(fs, dev_id, flags);
if (ret < 0) {
goto out;
}
ret = lfs_format(&fs->lfs, &fs->cfg);
if (ret < 0) {
LOG_ERR("format failed (LFS %d)", ret);
ret = lfs_to_errno(ret);
goto out;
}
out:
fs->backend = NULL;
fs_unlock(fs);
return ret;
}
#endif /* CONFIG_FILE_SYSTEM_MKFS */
static int littlefs_unmount(struct fs_mount_t *mountp) static int littlefs_unmount(struct fs_mount_t *mountp)
{ {
struct fs_littlefs *fs = mountp->fs_data; struct fs_littlefs *fs = mountp->fs_data;
@ -868,7 +935,7 @@ static int littlefs_unmount(struct fs_mount_t *mountp)
lfs_unmount(&fs->lfs); lfs_unmount(&fs->lfs);
if (!littlefs_on_blkdev(mountp)) { if (!littlefs_on_blkdev(mountp->flags)) {
flash_area_close(fs->backend); flash_area_close(fs->backend);
} }
@ -900,6 +967,9 @@ static const struct fs_file_system_t littlefs_fs = {
.mkdir = littlefs_mkdir, .mkdir = littlefs_mkdir,
.stat = littlefs_stat, .stat = littlefs_stat,
.statvfs = littlefs_statvfs, .statvfs = littlefs_statvfs,
#if defined(CONFIG_FILE_SYSTEM_MKFS)
.mkfs = littlefs_mkfs,
#endif
}; };
#define DT_DRV_COMPAT zephyr_fstab_littlefs #define DT_DRV_COMPAT zephyr_fstab_littlefs