fs: Implement mkfs operation in littleFS
Provide an implementation of fs_mkfs operation in littleFS.
Signed-off-by: Franciszek Zdobylak <fzdobylak@internships.antmicro.com>
diff --git a/subsys/fs/littlefs_fs.c b/subsys/fs/littlefs_fs.c
index e19c350..5265b84 100644
--- a/subsys/fs/littlefs_fs.c
+++ b/subsys/fs/littlefs_fs.c
@@ -58,10 +58,10 @@
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) &&
- mountp->flags & FS_MOUNT_FLAG_USE_DISK_ACCESS;
+ flags & FS_MOUNT_FLAG_USE_DISK_ACCESS;
}
static inline void *fc_allocate(size_t size)
@@ -619,10 +619,9 @@
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;
- struct fs_littlefs *fs = mountp->fs_data;
+ unsigned int area_id = (uintptr_t)dev_id;
const struct flash_area **fap = (const struct flash_area **)&fs->backend;
const struct device *dev;
int ret;
@@ -648,37 +647,29 @@
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;
- struct fs_littlefs *fs = mountp->fs_data;
- bool block_dev = littlefs_on_blkdev(mountp);
- 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;
- }
-
- /* 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;
+ if (littlefs_on_blkdev(flags)) {
+ fs->backend = (void *) dev_id;
ret = disk_access_init((char *) fs->backend);
if (ret < 0) {
LOG_ERR("Storage init ERROR!");
- goto out;
+ return ret;
}
} else {
- ret = littlefs_flash_init(mountp);
+ ret = littlefs_flash_init(fs, dev_id);
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_PROG_SIZE > 0);
@@ -708,13 +699,13 @@
lfs_size_t block_size = lcp->block_size;
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,
DISK_IOCTL_GET_SECTOR_SIZE,
&block_size);
if (ret < 0) {
LOG_ERR("Unable to get sector size");
- goto out;
+ return ret;
}
} else {
block_size = get_block_size((struct flash_area *)fs->backend);
@@ -723,8 +714,7 @@
if (block_size == 0) {
__ASSERT_NO_MSG(block_size != 0);
- ret = -EINVAL;
- goto out;
+ return -EINVAL;
}
int32_t block_cycles = lcp->block_cycles;
@@ -752,14 +742,13 @@
/* No, you don't get to override this. */
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,
DISK_IOCTL_GET_SECTOR_COUNT,
&block_count);
if (ret < 0) {
LOG_ERR("Unable to get sector count!");
- ret = -EINVAL;
- goto out;
+ return -EINVAL;
}
LOG_INF("FS at %s: is %u 0x%x-byte blocks with %u cycle",
(char *) fs->backend, block_count, block_size,
@@ -789,7 +778,7 @@
lcp->context = fs->backend;
/* 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->prog = lfs_api_prog_blk;
lcp->erase = lfs_api_erase_blk;
@@ -821,6 +810,46 @@
lcp->block_size = block_size;
lcp->block_count = block_count;
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. */
ret = lfs_mount(&fs->lfs, &fs->cfg);
@@ -860,6 +889,44 @@
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)
{
struct fs_littlefs *fs = mountp->fs_data;
@@ -868,7 +935,7 @@
lfs_unmount(&fs->lfs);
- if (!littlefs_on_blkdev(mountp)) {
+ if (!littlefs_on_blkdev(mountp->flags)) {
flash_area_close(fs->backend);
}
@@ -900,6 +967,9 @@
.mkdir = littlefs_mkdir,
.stat = littlefs_stat,
.statvfs = littlefs_statvfs,
+#if defined(CONFIG_FILE_SYSTEM_MKFS)
+ .mkfs = littlefs_mkfs,
+#endif
};
#define DT_DRV_COMPAT zephyr_fstab_littlefs