forked from Imagelibrary/littlefs
Changed block_size search to use erase_count when block_size is zero
This hopefully helps make it more clear that we are using erase_size as the unit during the block_size search. However this does mean you need to set erase_count to zero to allow any littlefs size, which might be a bit confusing: block_size block_count erase_size erase_count known known known known => known bs, O(1) known unknown known known => known bs, O(1) unknown unknown known known => bs search, O(d(n)) unknown unknown known unknown => bs search, O(n)
This commit is contained in:
25
lfs.c
25
lfs.c
@@ -4001,7 +4001,6 @@ static int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) {
|
||||
LFS_ASSERT(lfs->cfg->prog_size != 0);
|
||||
LFS_ASSERT(lfs->cfg->cache_size != 0);
|
||||
LFS_ASSERT(lfs->cfg->erase_size != 0 || lfs->cfg->block_size != 0);
|
||||
LFS_ASSERT(lfs->cfg->erase_count != 0 || lfs->cfg->block_count != 0);
|
||||
|
||||
// check that cache_size is a multiple of prog_size and read_size
|
||||
LFS_ASSERT(lfs->cfg->cache_size % lfs->cfg->read_size == 0);
|
||||
@@ -4222,21 +4221,23 @@ static int lfs_rawmount(lfs_t *lfs, const struct lfs_config *cfg) {
|
||||
if (!lfs->block_size) {
|
||||
lfs->block_size = lfs->erase_size;
|
||||
// make sure this doesn't overflow
|
||||
lfs_size_t limit = lfs->block_count
|
||||
? lfs->block_count/2
|
||||
: lfs->erase_count/2;
|
||||
if (limit > ((lfs_size_t)-1) / lfs->block_size) {
|
||||
if (!lfs->erase_count || lfs->erase_count/2
|
||||
> ((lfs_size_t)-1) / lfs->erase_size) {
|
||||
block_size_limit = ((lfs_size_t)-1);
|
||||
} else {
|
||||
block_size_limit = limit * lfs->block_size;
|
||||
block_size_limit = (lfs->erase_count/2) * lfs->erase_size;
|
||||
}
|
||||
}
|
||||
|
||||
// search for the correct block_size
|
||||
while (true) {
|
||||
// setup block_size/count so underlying operations work
|
||||
lfs->block_count = lfs->erase_count
|
||||
/ (lfs->block_size/lfs->erase_size);
|
||||
if (!lfs->erase_count) {
|
||||
lfs->block_count = (lfs_size_t)-1;
|
||||
} else {
|
||||
lfs->block_count = lfs->erase_count
|
||||
/ (lfs->block_size/lfs->erase_size);
|
||||
}
|
||||
|
||||
// scan directory blocks for superblock and any global updates
|
||||
lfs_mdir_t dir = {.tail = {0, 1}};
|
||||
@@ -4301,7 +4302,7 @@ static int lfs_rawmount(lfs_t *lfs, const struct lfs_config *cfg) {
|
||||
}
|
||||
|
||||
if (superblock.block_count != lfs->block_count) {
|
||||
if ((lfs->cfg->block_size && lfs->cfg->block_count)
|
||||
if (lfs->cfg->block_count
|
||||
|| superblock.block_count > lfs->block_count) {
|
||||
LFS_ERROR("Invalid block count %"PRIu32,
|
||||
superblock.block_count);
|
||||
@@ -4383,9 +4384,9 @@ next_block_size:
|
||||
}
|
||||
|
||||
// if block_count is set, skip block_sizes that aren't a factor,
|
||||
// this brings our search down from O(n) to O(d(n)), and
|
||||
// O(log(n)) for powers of 2
|
||||
if (lfs->cfg->block_count && lfs->cfg->block_count
|
||||
// this brings our search down from O(n) to O(d(n)), O(log(n))
|
||||
// on average, and O(log(n)) for powers of 2
|
||||
if (lfs->erase_count && lfs->erase_count
|
||||
% (lfs->block_size/lfs->erase_size) != 0) {
|
||||
goto next_block_size;
|
||||
}
|
||||
|
||||
15
lfs.h
15
lfs.h
@@ -209,6 +209,11 @@ struct lfs_config {
|
||||
//
|
||||
// If zero, the block_count is used as the erase_count. This is mostly for
|
||||
// backwards compatibility.
|
||||
//
|
||||
// If zero and block_count is zero, this is treated as unknown.
|
||||
//
|
||||
// If non-zero, littlefs will assume block_size is a factor of
|
||||
// erase_size*erase_count to speed up mount when no superblock is found.
|
||||
lfs_size_t erase_count;
|
||||
|
||||
// Size of a logical block in bytes. This does not impact RAM consumption
|
||||
@@ -223,18 +228,14 @@ struct lfs_config {
|
||||
// block_size, but it can take time to fail if a superblock is not found:
|
||||
//
|
||||
// - O(block_size) if a superblock is found
|
||||
// - O(d(block_count)) if block_count is non-zero
|
||||
// - O(log(block_count)) if block_count is a power of 2
|
||||
// - O(erase_count) if block_count is zero
|
||||
// - O(d(erase_count)) if erase_count is non-zero
|
||||
// - O(log(erase_count)) if erase_count is a power of 2
|
||||
// - O(erase_count) if erase_count is zero
|
||||
lfs_size_t block_size;
|
||||
|
||||
// Number of logical blocks on the device.
|
||||
//
|
||||
// If zero, littlefs uses the block_count stored in the superblock.
|
||||
//
|
||||
// If non-zero and block_size is zero, littlefs will assume block_size
|
||||
// is a factor of erase_size*block_count to speed up mount when no
|
||||
// superblock is found.
|
||||
lfs_size_t block_count;
|
||||
|
||||
// Number of erase cycles before littlefs evicts metadata logs and moves
|
||||
|
||||
Reference in New Issue
Block a user