diff --git a/lfs.c b/lfs.c index d7439fe3..5585b40b 100644 --- a/lfs.c +++ b/lfs.c @@ -1589,7 +1589,7 @@ static int lfs_dir_compact(lfs_t *lfs, // for metadata updates. if (end - begin < 0xff && size <= lfs_min(lfs->cfg->block_size - 36, - lfs_alignup(lfs->cfg->block_size/2, + lfs_alignup(lfs->metadata_max/2, lfs->cfg->prog_size))) { break; } @@ -1674,7 +1674,7 @@ static int lfs_dir_compact(lfs_t *lfs, .crc = 0xffffffff, .begin = 0, - .end = lfs->cfg->block_size - 8, + .end = lfs->metadata_max - 8, }; // erase block to write to @@ -1884,7 +1884,7 @@ static int lfs_dir_commit(lfs_t *lfs, lfs_mdir_t *dir, .crc = 0xffffffff, .begin = dir->off, - .end = lfs->cfg->block_size - 8, + .end = lfs->metadata_max - 8, }; // traverse attrs that need to be written out @@ -2966,7 +2966,7 @@ static lfs_ssize_t lfs_file_rawwrite(lfs_t *lfs, lfs_file_t *file, if ((file->flags & LFS_F_INLINE) && lfs_max(file->pos+nsize, file->ctz.size) > lfs_min(0x3fe, lfs_min( - lfs->cfg->cache_size, lfs->cfg->block_size/8))) { + lfs->cfg->cache_size, lfs->inline_file_max))) { // inline file doesn't fit anymore int err = lfs_file_outline(lfs, file); if (err) { @@ -3536,6 +3536,20 @@ static int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) { lfs->attr_max = LFS_ATTR_MAX; } + LFS_ASSERT(lfs->cfg->metadata_max <= lfs->cfg->block_size); + lfs->metadata_max = lfs->cfg->metadata_max; + if (!lfs->metadata_max) { + lfs->metadata_max = lfs->cfg->block_size; + } + + LFS_ASSERT(lfs->cfg->inline_file_max <= LFS_FILE_MAX); + lfs->inline_file_max = lfs->cfg->inline_file_max; + if (!lfs->inline_file_max) { + lfs->inline_file_max = lfs->cfg->block_size / 8; + } else if(lfs->inline_file_max == -1) { + lfs->inline_file_max = 0; + } + // setup default state lfs->root[0] = LFS_BLOCK_NULL; lfs->root[1] = LFS_BLOCK_NULL; @@ -3829,7 +3843,7 @@ int lfs_fs_rawtraverse(lfs_t *lfs, if (err) { return err; } - } else if (includeorphans && + } else if (includeorphans && lfs_tag_type3(tag) == LFS_TYPE_DIRSTRUCT) { for (int i = 0; i < 2; i++) { err = cb(data, (&ctz.head)[i]); diff --git a/lfs.h b/lfs.h index 3b02b6a7..8a4b1d0c 100644 --- a/lfs.h +++ b/lfs.h @@ -207,7 +207,7 @@ struct lfs_config { // Number of erasable blocks on the device. 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 // the metadata to another block. Suggested values are in the // range 100-1000, with large values having better performance at the cost // of less consistent wear distribution. @@ -256,6 +256,20 @@ struct lfs_config { // larger attributes size but must be <= LFS_ATTR_MAX. Defaults to // LFS_ATTR_MAX when zero. lfs_size_t attr_max; + + // Optional upper limit on total space given to metadata pairs in bytes. On + // devices with large blocks (e.g. 128kB) setting this to a low size (2-8kB) + // can help bound the metadata compaction time. Must be <= block_size. + // Defaults to block_size when zero. + lfs_size_t metadata_max; + + // Optional upper limit on inline files in bytes. On devices with large + // blocks (e.g. 128kB) setting this to a low size or disabling inline files + // can help bound file read overhead. Must be <= LFS_FILE_MAX. Defaults to + // block_size/8 when zero. + // + // Set to -1 to disable inline files. + lfs_ssize_t inline_file_max; }; // File info structure @@ -406,6 +420,8 @@ typedef struct lfs { lfs_size_t name_max; lfs_size_t file_max; lfs_size_t attr_max; + lfs_size_t metadata_max; + lfs_ssize_t inline_file_max; #ifdef LFS_MIGRATE struct lfs1 *lfs1;