Skip to content

Commit

Permalink
Merge pull request #18141 from fabian18/filesystems_configure_block_size
Browse files Browse the repository at this point in the history
littlefs: make block size configurable at compile time
  • Loading branch information
benpicco authored Jul 31, 2022
2 parents 66452d1 + 578e628 commit f375856
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 29 deletions.
39 changes: 27 additions & 12 deletions pkg/littlefs/fs/littlefs_fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,29 +62,29 @@ static int littlefs_err_to_errno(ssize_t err)
}

static int _dev_read(const struct lfs_config *c, lfs_block_t block,
lfs_off_t off, void *buffer, lfs_size_t size)
lfs_off_t off, void *buffer, lfs_size_t size)
{
littlefs_desc_t *fs = c->context;
mtd_dev_t *mtd = fs->dev;

DEBUG("lfs_read: c=%p, block=%" PRIu32 ", off=%" PRIu32 ", buf=%p, size=%" PRIu32 "\n",
(void *)c, block, off, buffer, size);

return mtd_read_page(mtd, buffer, (fs->base_addr + block) * mtd->pages_per_sector,
off, size);
uint32_t page = (fs->base_addr + block) * fs->sectors_per_block * mtd->pages_per_sector;
return mtd_read_page(mtd, buffer, page, off, size);
}

static int _dev_write(const struct lfs_config *c, lfs_block_t block,
lfs_off_t off, const void *buffer, lfs_size_t size)
lfs_off_t off, const void *buffer, lfs_size_t size)
{
littlefs_desc_t *fs = c->context;
mtd_dev_t *mtd = fs->dev;

DEBUG("lfs_write: c=%p, block=%" PRIu32 ", off=%" PRIu32 ", buf=%p, size=%" PRIu32 "\n",
(void *)c, block, off, buffer, size);

return mtd_write_page_raw(mtd, buffer, (fs->base_addr + block) * mtd->pages_per_sector,
off, size);
uint32_t page = (fs->base_addr + block) * fs->sectors_per_block * mtd->pages_per_sector;
return mtd_write_page_raw(mtd, buffer, page, off, size);
}

static int _dev_erase(const struct lfs_config *c, lfs_block_t block)
Expand All @@ -94,7 +94,8 @@ static int _dev_erase(const struct lfs_config *c, lfs_block_t block)

DEBUG("lfs_erase: c=%p, block=%" PRIu32 "\n", (void *)c, block);

return mtd_erase_sector(mtd, fs->base_addr + block, 1);
uint32_t sector = (fs->base_addr + block) * fs->sectors_per_block;
return mtd_erase_sector(mtd, sector, fs->sectors_per_block);
}

static int _dev_sync(const struct lfs_config *c)
Expand All @@ -117,11 +118,24 @@ static int prepare(littlefs_desc_t *fs)

memset(&fs->fs, 0, sizeof(fs->fs));

if (!fs->config.block_count) {
fs->config.block_count = fs->dev->sector_count - fs->base_addr;
}
static_assert(0 > LITTLEFS_MIN_BLOCK_SIZE_EXP ||
6 < LITTLEFS_MIN_BLOCK_SIZE_EXP,
"LITTLEFS_MIN_BLOCK_SIZE_EXP must be at least 7, "
"to configure a reasonable block size of at least 128 bytes.");

size_t block_size = fs->dev->pages_per_sector * fs->dev->page_size;
#if LITTLEFS_MIN_BLOCK_SIZE_EXP >= 0
block_size = ((block_size - 1) + (1u << LITTLEFS_MIN_BLOCK_SIZE_EXP))
/ block_size * block_size;
#endif
fs->sectors_per_block = block_size / (fs->dev->pages_per_sector * fs->dev->page_size);
size_t block_count = fs->dev->sector_count / fs->sectors_per_block;

if (!fs->config.block_size) {
fs->config.block_size = fs->dev->page_size * fs->dev->pages_per_sector;
fs->config.block_size = block_size;
}
if (!fs->config.block_count) {
fs->config.block_count = block_count - fs->base_addr;
}
if (!fs->config.prog_size) {
fs->config.prog_size = fs->dev->page_size;
Expand Down Expand Up @@ -443,7 +457,8 @@ static int _statvfs(vfs_mount_t *mountp, const char *restrict path, struct statv
mutex_unlock(&fs->lock);

buf->f_bsize = fs->fs.cfg->block_size; /* block size */
buf->f_frsize = fs->fs.cfg->block_size; /* fundamental block size */
buf->f_frsize = fs->dev->page_size *
fs->dev->pages_per_sector; /* fundamental block size */
buf->f_blocks = fs->fs.cfg->block_count; /* Blocks total */
buf->f_bfree = buf->f_blocks - nb_blocks; /* Blocks free */
buf->f_bavail = buf->f_blocks - nb_blocks; /* Blocks available to non-privileged processes */
Expand Down
9 changes: 9 additions & 0 deletions pkg/littlefs2/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,13 @@ config LITTLEFS2_BLOCK_CYCLES
Sets the maximum number of erase cycles before blocks are evicted as a part
of wear leveling. -1 disables wear-leveling.

config LITTLEFS2_MIN_BLOCK_SIZE_EXP
int "Minimum acceptable block size"
range -1 15
default -1
help
Sets the exponent of the minimum acceptable block size in bytes (2^n).
The actual block size may be larger due to device properties.
The default value (-1) sets the block size to the smalles possible value.

endif # MODULE_LITTLEFS2_FS
40 changes: 27 additions & 13 deletions pkg/littlefs2/fs/littlefs2_fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,29 +62,29 @@ static int littlefs_err_to_errno(ssize_t err)
}

static int _dev_read(const struct lfs_config *c, lfs_block_t block,
lfs_off_t off, void *buffer, lfs_size_t size)
lfs_off_t off, void *buffer, lfs_size_t size)
{
littlefs2_desc_t *fs = c->context;
mtd_dev_t *mtd = fs->dev;

DEBUG("lfs_read: c=%p, block=%" PRIu32 ", off=%" PRIu32 ", buf=%p, size=%" PRIu32 "\n",
(void *)c, block, off, buffer, size);

return mtd_read_page(mtd, buffer, (fs->base_addr + block) * mtd->pages_per_sector,
off, size);
uint32_t page = (fs->base_addr + block) * fs->sectors_per_block * mtd->pages_per_sector;
return mtd_read_page(mtd, buffer, page, off, size);
}

static int _dev_write(const struct lfs_config *c, lfs_block_t block,
lfs_off_t off, const void *buffer, lfs_size_t size)
lfs_off_t off, const void *buffer, lfs_size_t size)
{
littlefs2_desc_t *fs = c->context;
mtd_dev_t *mtd = fs->dev;

DEBUG("lfs_write: c=%p, block=%" PRIu32 ", off=%" PRIu32 ", buf=%p, size=%" PRIu32 "\n",
(void *)c, block, off, buffer, size);

return mtd_write_page_raw(mtd, buffer, (fs->base_addr + block) * mtd->pages_per_sector,
off, size);
uint32_t page = (fs->base_addr + block) * fs->sectors_per_block * mtd->pages_per_sector;
return mtd_write_page_raw(mtd, buffer, page, off, size);
}

static int _dev_erase(const struct lfs_config *c, lfs_block_t block)
Expand All @@ -94,8 +94,8 @@ static int _dev_erase(const struct lfs_config *c, lfs_block_t block)

DEBUG("lfs_erase: c=%p, block=%" PRIu32 "\n", (void *)c, block);

return mtd_erase_sector(mtd, fs->base_addr + block, 1);
}
uint32_t sector = (fs->base_addr + block) * fs->sectors_per_block;
return mtd_erase_sector(mtd, sector, fs->sectors_per_block);}

static int _dev_sync(const struct lfs_config *c)
{
Expand All @@ -117,11 +117,24 @@ static int prepare(littlefs2_desc_t *fs)

memset(&fs->fs, 0, sizeof(fs->fs));

if (!fs->config.block_count) {
fs->config.block_count = fs->dev->sector_count - fs->base_addr;
}
static_assert(0 > CONFIG_LITTLEFS2_MIN_BLOCK_SIZE_EXP ||
6 < CONFIG_LITTLEFS2_MIN_BLOCK_SIZE_EXP,
"CONFIG_LITTLEFS2_MIN_BLOCK_SIZE_EXP must be at least 7, "
"to configure a reasonable block size of at least 128 bytes.");

size_t block_size = fs->dev->pages_per_sector * fs->dev->page_size;
#if CONFIG_LITTLEFS2_MIN_BLOCK_SIZE_EXP >= 0
block_size = ((block_size - 1) + (1u << CONFIG_LITTLEFS2_MIN_BLOCK_SIZE_EXP))
/ block_size * block_size;
#endif
fs->sectors_per_block = block_size / (fs->dev->pages_per_sector * fs->dev->page_size);
size_t block_count = fs->dev->sector_count / fs->sectors_per_block;

if (!fs->config.block_size) {
fs->config.block_size = fs->dev->page_size * fs->dev->pages_per_sector;
fs->config.block_size = block_size;
}
if (!fs->config.block_count) {
fs->config.block_count = block_count - fs->base_addr;
}
if (!fs->config.prog_size) {
fs->config.prog_size = fs->dev->page_size;
Expand Down Expand Up @@ -449,7 +462,8 @@ static int _statvfs(vfs_mount_t *mountp, const char *restrict path, struct statv
mutex_unlock(&fs->lock);

buf->f_bsize = fs->fs.cfg->block_size; /* block size */
buf->f_frsize = fs->fs.cfg->block_size; /* fundamental block size */
buf->f_frsize = fs->dev->page_size *
fs->dev->pages_per_sector; /* fundamental block size */
buf->f_blocks = fs->fs.cfg->block_count; /* Blocks total */
buf->f_bfree = buf->f_blocks - nb_blocks; /* Blocks free */
buf->f_bavail = buf->f_blocks - nb_blocks; /* Blocks available to non-privileged processes */
Expand Down
8 changes: 8 additions & 0 deletions sys/include/fs/littlefs2_fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,13 @@ extern "C" {
* of wear leveling. -1 disables wear-leveling. */
#define CONFIG_LITTLEFS2_BLOCK_CYCLES (512)
#endif

#ifndef CONFIG_LITTLEFS2_MIN_BLOCK_SIZE_EXP
/**
* The exponent of the minimum acceptable block size in bytes (2^n).
* The desired block size is not guaranteed to be applicable but will be respected. */
#define CONFIG_LITTLEFS2_MIN_BLOCK_SIZE_EXP (-1)
#endif
/** @} */

/**
Expand All @@ -88,6 +95,7 @@ typedef struct {
* total number of block is defined in @p config.
* if set to 0, the total number of sectors from the mtd is used */
uint32_t base_addr;
uint16_t sectors_per_block; /**< number of sectors per block */
#if CONFIG_LITTLEFS2_FILE_BUFFER_SIZE || DOXYGEN
/** file buffer to use internally if CONFIG_LITTLEFS2_FILE_BUFFER_SIZE
* is set */
Expand Down
8 changes: 8 additions & 0 deletions sys/include/fs/littlefs_fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,13 @@ extern "C" {
* If set, it must be program size */
#define LITTLEFS_PROG_BUFFER_SIZE (0)
#endif

#ifndef LITTLEFS_MIN_BLOCK_SIZE_EXP
/**
* The exponent of the minimum acceptable block size in bytes (2^n).
* The desired block size is not guaranteed to be applicable but will be respected. */
#define LITTLEFS_MIN_BLOCK_SIZE_EXP (-1)
#endif
/** @} */

/**
Expand All @@ -72,6 +79,7 @@ typedef struct {
* total number of block is defined in @p config.
* if set to 0, the total number of sectors from the mtd is used */
uint32_t base_addr;
uint16_t sectors_per_block; /**< number of sectors per block */
#if LITTLEFS_FILE_BUFFER_SIZE || DOXYGEN
/** file buffer to use internally if LITTLEFS_FILE_BUFFER_SIZE is set */
uint8_t file_buf[LITTLEFS_FILE_BUFFER_SIZE];
Expand Down
10 changes: 8 additions & 2 deletions tests/pkg_littlefs/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,10 @@ static void tests_littlefs_statvfs(void)

int res = vfs_statvfs("/test-littlefs/", &stat1);
TEST_ASSERT_EQUAL_INT(0, res);
TEST_ASSERT_EQUAL_INT(_dev->page_size * _dev->pages_per_sector, stat1.f_bsize);
TEST_ASSERT_EQUAL_INT(_dev->page_size *
_dev->pages_per_sector *
littlefs_desc.sectors_per_block,
stat1.f_bsize);
TEST_ASSERT_EQUAL_INT(_dev->page_size * _dev->pages_per_sector, stat1.f_frsize);
TEST_ASSERT((_dev->pages_per_sector * _dev->page_size * _dev->sector_count) >=
stat1.f_blocks);
Expand All @@ -400,7 +403,10 @@ static void tests_littlefs_statvfs(void)
res = vfs_statvfs("/test-littlefs/", &stat2);
TEST_ASSERT_EQUAL_INT(0, res);

TEST_ASSERT_EQUAL_INT(_dev->page_size * _dev->pages_per_sector, stat2.f_bsize);
TEST_ASSERT_EQUAL_INT(_dev->page_size *
_dev->pages_per_sector *
littlefs_desc.sectors_per_block,
stat2.f_bsize);
TEST_ASSERT_EQUAL_INT(_dev->page_size * _dev->pages_per_sector, stat2.f_frsize);
TEST_ASSERT(stat1.f_bfree > stat2.f_bfree);
TEST_ASSERT(stat1.f_bavail > stat2.f_bavail);
Expand Down
10 changes: 8 additions & 2 deletions tests/pkg_littlefs2/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,10 @@ static void tests_littlefs_statvfs(void)

int res = vfs_statvfs("/test-littlefs/", &stat1);
TEST_ASSERT_EQUAL_INT(0, res);
TEST_ASSERT_EQUAL_INT(_dev->page_size * _dev->pages_per_sector, stat1.f_bsize);
TEST_ASSERT_EQUAL_INT(_dev->page_size *
_dev->pages_per_sector *
littlefs_desc.sectors_per_block,
stat1.f_bsize);
TEST_ASSERT_EQUAL_INT(_dev->page_size * _dev->pages_per_sector, stat1.f_frsize);
TEST_ASSERT((_dev->pages_per_sector * _dev->page_size * _dev->sector_count) >=
stat1.f_blocks);
Expand All @@ -402,7 +405,10 @@ static void tests_littlefs_statvfs(void)
res = vfs_statvfs("/test-littlefs/", &stat2);
TEST_ASSERT_EQUAL_INT(0, res);

TEST_ASSERT_EQUAL_INT(_dev->page_size * _dev->pages_per_sector, stat2.f_bsize);
TEST_ASSERT_EQUAL_INT(_dev->page_size *
_dev->pages_per_sector *
littlefs_desc.sectors_per_block,
stat2.f_bsize);
TEST_ASSERT_EQUAL_INT(_dev->page_size * _dev->pages_per_sector, stat2.f_frsize);
TEST_ASSERT(stat1.f_bfree > stat2.f_bfree);
TEST_ASSERT(stat1.f_bavail > stat2.f_bavail);
Expand Down

0 comments on commit f375856

Please sign in to comment.