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:
@@ -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->prog_size != 0);
|
||||||
LFS_ASSERT(lfs->cfg->cache_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_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
|
// check that cache_size is a multiple of prog_size and read_size
|
||||||
LFS_ASSERT(lfs->cfg->cache_size % lfs->cfg->read_size == 0);
|
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) {
|
if (!lfs->block_size) {
|
||||||
lfs->block_size = lfs->erase_size;
|
lfs->block_size = lfs->erase_size;
|
||||||
// make sure this doesn't overflow
|
// make sure this doesn't overflow
|
||||||
lfs_size_t limit = lfs->block_count
|
if (!lfs->erase_count || lfs->erase_count/2
|
||||||
? lfs->block_count/2
|
> ((lfs_size_t)-1) / lfs->erase_size) {
|
||||||
: lfs->erase_count/2;
|
|
||||||
if (limit > ((lfs_size_t)-1) / lfs->block_size) {
|
|
||||||
block_size_limit = ((lfs_size_t)-1);
|
block_size_limit = ((lfs_size_t)-1);
|
||||||
} else {
|
} else {
|
||||||
block_size_limit = limit * lfs->block_size;
|
block_size_limit = (lfs->erase_count/2) * lfs->erase_size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// search for the correct block_size
|
// search for the correct block_size
|
||||||
while (true) {
|
while (true) {
|
||||||
// setup block_size/count so underlying operations work
|
// setup block_size/count so underlying operations work
|
||||||
|
if (!lfs->erase_count) {
|
||||||
|
lfs->block_count = (lfs_size_t)-1;
|
||||||
|
} else {
|
||||||
lfs->block_count = lfs->erase_count
|
lfs->block_count = lfs->erase_count
|
||||||
/ (lfs->block_size/lfs->erase_size);
|
/ (lfs->block_size/lfs->erase_size);
|
||||||
|
}
|
||||||
|
|
||||||
// scan directory blocks for superblock and any global updates
|
// scan directory blocks for superblock and any global updates
|
||||||
lfs_mdir_t dir = {.tail = {0, 1}};
|
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 (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) {
|
|| superblock.block_count > lfs->block_count) {
|
||||||
LFS_ERROR("Invalid block count %"PRIu32,
|
LFS_ERROR("Invalid block count %"PRIu32,
|
||||||
superblock.block_count);
|
superblock.block_count);
|
||||||
@@ -4383,9 +4384,9 @@ next_block_size:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// if block_count is set, skip block_sizes that aren't a factor,
|
// 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
|
// this brings our search down from O(n) to O(d(n)), O(log(n))
|
||||||
// O(log(n)) for powers of 2
|
// on average, and O(log(n)) for powers of 2
|
||||||
if (lfs->cfg->block_count && lfs->cfg->block_count
|
if (lfs->erase_count && lfs->erase_count
|
||||||
% (lfs->block_size/lfs->erase_size) != 0) {
|
% (lfs->block_size/lfs->erase_size) != 0) {
|
||||||
goto next_block_size;
|
goto next_block_size;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -209,6 +209,11 @@ struct lfs_config {
|
|||||||
//
|
//
|
||||||
// If zero, the block_count is used as the erase_count. This is mostly for
|
// If zero, the block_count is used as the erase_count. This is mostly for
|
||||||
// backwards compatibility.
|
// 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;
|
lfs_size_t erase_count;
|
||||||
|
|
||||||
// Size of a logical block in bytes. This does not impact RAM consumption
|
// 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:
|
// block_size, but it can take time to fail if a superblock is not found:
|
||||||
//
|
//
|
||||||
// - O(block_size) if a superblock is found
|
// - O(block_size) if a superblock is found
|
||||||
// - O(d(block_count)) if block_count is non-zero
|
// - O(d(erase_count)) if erase_count is non-zero
|
||||||
// - O(log(block_count)) if block_count is a power of 2
|
// - O(log(erase_count)) if erase_count is a power of 2
|
||||||
// - O(erase_count) if block_count is zero
|
// - O(erase_count) if erase_count is zero
|
||||||
lfs_size_t block_size;
|
lfs_size_t block_size;
|
||||||
|
|
||||||
// Number of logical blocks on the device.
|
// Number of logical blocks on the device.
|
||||||
//
|
//
|
||||||
// If zero, littlefs uses the block_count stored in the superblock.
|
// 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;
|
lfs_size_t block_count;
|
||||||
|
|
||||||
// Number of erase cycles before littlefs evicts metadata logs and moves
|
// Number of erase cycles before littlefs evicts metadata logs and moves
|
||||||
|
|||||||
Reference in New Issue
Block a user