M module-vfs/drivers/src/purefs/fs/filesystem_littlefs.cpp => module-vfs/drivers/src/purefs/fs/filesystem_littlefs.cpp +37 -9
@@ 6,10 6,13 @@
#include <littlefs/volume_mapper.hpp>
#include <purefs/fs/drivers/file_handle_littlefs.hpp>
#include <purefs/fs/drivers/directory_handle_littlefs.hpp>
+#include <purefs/blkdev/disk_manager.hpp>
+#include <purefs/blkdev/disk_handle.hpp>
#include <lfs.h>
+#include <lfs_extension.h>
#include <log/log.hpp>
-#include <limits.h>
+#include <climits>
#include <syslimits.h>
#include <sys/statvfs.h>
#include <fcntl.h>
@@ 103,19 106,33 @@ namespace
st.st_mode = translate_attrib_to_st_mode(fs.type);
}
- [[gnu::nonnull(1)]] void setup_lfs_config(lfs_config *cfg)
+ [[gnu::nonnull(1)]] int setup_lfs_config(lfs_config *cfg, size_t sector_size, size_t part_sectors_count)
{
cfg->block_cycles = 512;
cfg->block_size = 0; // Read later from superblock
cfg->block_count = 0; // Read later from super block
cfg->lookahead_size = 8192;
- // TODO: Read lfs configuration from the superblock
- cfg->block_size = 4096;
- cfg->read_size = cfg->block_size;
- cfg->prog_size = cfg->block_size;
- cfg->cache_size = cfg->block_size;
- cfg->block_count = 261887;
+
+ int err = lfs_extension_read_config_from_superblock(cfg, sector_size);
+ if (err) {
+ LOG_ERROR("Unable to read the superblock info %i", err);
+ return lfs_to_errno(err);
+ }
+ if (cfg->block_size > 1024U * 1024U) {
+ LOG_ERROR("Block size too big");
+ return -E2BIG;
+ }
+
+ if ((uint64_t(cfg->block_count) * uint64_t(cfg->block_size)) / sector_size > part_sectors_count) {
+ LOG_ERROR("Block count out of range sectors count");
+ return -ERANGE;
+ }
+ cfg->read_size = cfg->block_size;
+ cfg->prog_size = cfg->block_size;
+ cfg->cache_size = cfg->block_size;
+ return 0;
}
+
} // namespace
namespace purefs::fs::drivers
@@ 227,9 244,20 @@ namespace purefs::fs::drivers
cpp_freertos::LockGuard _lck(m_lock);
auto err = littlefs::internal::append_volume(vmnt->lfs_config(), disk_mngr(), disk);
if (err) {
+ return lfs_to_errno(err);
+ }
+ {
+ auto diskmm = disk_mngr();
+ auto ssize = diskmm->get_info(disk, blkdev::info_type::sector_size);
+ if (ssize < 0) {
+ LOG_ERROR("Unable to read sector size %i", int(ssize));
+ return ssize;
+ }
+ err = setup_lfs_config(vmnt->lfs_config(), ssize, disk->sectors());
+ }
+ if (err) {
return err;
}
- setup_lfs_config(vmnt->lfs_config());
err = lfs_mount(vmnt->lfs_mount(), vmnt->lfs_config());
if (err) {
LOG_ERROR("LFS mount error %i", err);
M module-vfs/thirdparty/lfsfs/CMakeLists.txt => module-vfs/thirdparty/lfsfs/CMakeLists.txt +5 -2
@@ 5,6 5,8 @@ project(littlefs LANGUAGES C)
include(thirdparty OPTIONAL)
set(LIBLITTLEFS_SRCDIR littlefs)
+set(LIBLITTLEFS_SRCDIR_EXT lfsextension/src)
+set(LIBLITTLEFS_INCDIR_EXT lfsextension/include)
set(LIBLITTLEFS_TARGET ${PROJECT_NAME})
set(LIBLITTLEFS_SOURCES
@@ 13,10 15,11 @@ set(LIBLITTLEFS_SOURCES
${LIBLITTLEFS_SRCDIR}/bd/lfs_filebd.c
${LIBLITTLEFS_SRCDIR}/bd/lfs_rambd.c
${LIBLITTLEFS_SRCDIR}/bd/lfs_testbd.c
+ ${LIBLITTLEFS_SRCDIR_EXT}/lfs_extension.c
)
-set( LIBLITTLEFS_PUBLIC_INCLUDES ${LIBLITTLEFS_SRCDIR})
-set( LIBLITTLEFS_PRIVATE_INCLUDES ${LIBLITTLEFS_SRCDIR}/bd)
+set( LIBLITTLEFS_PUBLIC_INCLUDES ${LIBLITTLEFS_SRCDIR} ${LIBLITTLEFS_INCDIR_EXT})
+set( LIBLITTLEFS_PRIVATE_INCLUDES ${LIBLITTLEFS_SRCDIR}/bd )
add_library( ${LIBLITTLEFS_TARGET} STATIC ${LIBLITTLEFS_SOURCES} )
A module-vfs/thirdparty/lfsfs/lfsextension/include/lfs_extension.h => module-vfs/thirdparty/lfsfs/lfsextension/include/lfs_extension.h +21 -0
@@ 0,0 1,21 @@
+// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include "lfs.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+ /**
+ * Try to setup config structure based on the superblock information
+ * @param cfg LFS config structure
+ * @return 0 or success otherwise error
+ */
+ int lfs_extension_read_config_from_superblock(struct lfs_config *cfg, size_t sector_size)
+ __attribute__((nonnull(1)));
+#ifdef __cplusplus
+}
+#endif
A module-vfs/thirdparty/lfsfs/lfsextension/src/lfs_extension.c => module-vfs/thirdparty/lfsfs/lfsextension/src/lfs_extension.c +68 -0
@@ 0,0 1,68 @@
+// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "lfs_extension.h"
+#include "lfs_util.h"
+
+static inline void lfs_superblock_fromle32(lfs_superblock_t *superblock)
+{
+ superblock->version = lfs_fromle32(superblock->version);
+ superblock->block_size = lfs_fromle32(superblock->block_size);
+ superblock->block_count = lfs_fromle32(superblock->block_count);
+ superblock->name_max = lfs_fromle32(superblock->name_max);
+ superblock->file_max = lfs_fromle32(superblock->file_max);
+ superblock->attr_max = lfs_fromle32(superblock->attr_max);
+}
+
+static void *memstr(const void *mem, size_t memsize, const char *str)
+{
+ const size_t findstr_len = strlen(str);
+ const uint8_t *memu8p = mem;
+ if (findstr_len > memsize) {
+ return NULL;
+ }
+ uint8_t *match = memchr(memu8p, str[0], memsize);
+ if (match != NULL) {
+ size_t remaining = memsize - ((uint8_t *)match - memu8p);
+ if (findstr_len <= remaining) {
+ if (memcmp(match, str, findstr_len) == 0) {
+ return match;
+ }
+ }
+ }
+ return NULL;
+}
+
+int lfs_extension_read_config_from_superblock(struct lfs_config *cfg, size_t sector_size)
+{
+ uint8_t sect_buf[sector_size] __attribute__((aligned));
+ if (!cfg->read) {
+ return LFS_ERR_IO;
+ }
+ lfs_superblock_t *lfs_superblock;
+ if (sector_size <= sizeof(*lfs_superblock)) {
+ return LFS_ERR_IO;
+ }
+ lfs_size_t block_size_saved = cfg->block_size;
+ int err = cfg->read(cfg, 0, 0, sect_buf, sector_size);
+ cfg->block_size = block_size_saved;
+ if (err) {
+ return err;
+ }
+ const uint8_t *ptr = memstr(sect_buf, sizeof sect_buf, "littlefs");
+ if (!ptr) {
+ return LFS_ERR_NOENT;
+ }
+ lfs_superblock = (lfs_superblock_t *)(ptr + 12);
+ lfs_superblock_fromle32(lfs_superblock);
+ // check version
+ uint16_t major_version = (0xffff & (lfs_superblock->version >> 16));
+ uint16_t minor_version = (0xffff & (lfs_superblock->version >> 0));
+ if ((major_version != LFS_DISK_VERSION_MAJOR || minor_version > LFS_DISK_VERSION_MINOR)) {
+ LFS_ERROR("Invalid version v%" PRIu16 ".%" PRIu16, major_version, minor_version);
+ return LFS_ERR_INVAL;
+ }
+ cfg->block_size = lfs_superblock->block_size;
+ cfg->block_count = lfs_superblock->block_count;
+ return LFS_ERR_OK;
+}