Changed lookahead configuration unit to bytes instead of bits

The fact that the lookahead buffer uses bits instead of bytes is an
internal detail. Poking this through to the user API has caused a decent
amount of confusion. Most buffers are provided as bytes and the
inconsistency here can be surprising.

The use of bytes instead of bits also makes us forward compatible in
the case that we want to change the lookahead internal representation
(hint segment list).

Additionally, we change the configuration name to lookahead_size. This
matches other configurations, such as cache_size and read_size, while
also notifying the user that something important changed at compile time
(by breaking).
This commit is contained in:
Christopher Haster
2018-10-02 20:18:30 -05:00
parent ad96fca18f
commit 7af8b81b81
5 changed files with 41 additions and 37 deletions

View File

@@ -20,7 +20,7 @@ script:
# run tests with a few different configurations # run tests with a few different configurations
- make test QUIET=1 CFLAGS+="-DLFS_READ_SIZE=1 -DLFS_CACHE_SIZE=4" - make test QUIET=1 CFLAGS+="-DLFS_READ_SIZE=1 -DLFS_CACHE_SIZE=4"
- make test QUIET=1 CFLAGS+="-DLFS_READ_SIZE=512 -DLFS_CACHE_SIZE=512 -DLFS_BLOCK_CYCLES=16" - make test QUIET=1 CFLAGS+="-DLFS_READ_SIZE=512 -DLFS_CACHE_SIZE=512 -DLFS_BLOCK_CYCLES=16"
- make test QUIET=1 CFLAGS+="-DLFS_BLOCK_COUNT=1023 -DLFS_LOOKAHEAD=2048" - make test QUIET=1 CFLAGS+="-DLFS_BLOCK_COUNT=1023 -DLFS_LOOKAHEAD_SIZE=256"
- make clean test QUIET=1 CFLAGS+="-DLFS_INLINE_MAX=0" - make clean test QUIET=1 CFLAGS+="-DLFS_INLINE_MAX=0"
- make clean test QUIET=1 CFLAGS+="-DLFS_NO_INTRINSICS" - make clean test QUIET=1 CFLAGS+="-DLFS_NO_INTRINSICS"

View File

@@ -49,7 +49,8 @@ const struct lfs_config cfg = {
.prog_size = 16, .prog_size = 16,
.block_size = 4096, .block_size = 4096,
.block_count = 128, .block_count = 128,
.lookahead = 128, .cache_size = 16,
.lookahead_size = 16,
}; };
// entry point // entry point

15
lfs.c
View File

@@ -462,11 +462,11 @@ static int lfs_alloc(lfs_t *lfs, lfs_block_t *block) {
lfs->free.off = (lfs->free.off + lfs->free.size) lfs->free.off = (lfs->free.off + lfs->free.size)
% lfs->cfg->block_count; % lfs->cfg->block_count;
lfs->free.size = lfs_min(lfs->cfg->lookahead, lfs->free.ack); lfs->free.size = lfs_min(8*lfs->cfg->lookahead_size, lfs->free.ack);
lfs->free.i = 0; lfs->free.i = 0;
// find mask of free blocks from tree // find mask of free blocks from tree
memset(lfs->free.buffer, 0, lfs->cfg->lookahead/8); memset(lfs->free.buffer, 0, lfs->cfg->lookahead_size);
int err = lfs_fs_traverse(lfs, lfs_alloc_lookahead, lfs); int err = lfs_fs_traverse(lfs, lfs_alloc_lookahead, lfs);
if (err) { if (err) {
return err; return err;
@@ -3041,12 +3041,12 @@ static int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) {
lfs_cache_zero(lfs, &lfs->pcache); lfs_cache_zero(lfs, &lfs->pcache);
// setup lookahead, must be multiple of 32-bits // setup lookahead, must be multiple of 32-bits
LFS_ASSERT(lfs->cfg->lookahead % 32 == 0); LFS_ASSERT(lfs->cfg->lookahead_size % 4 == 0);
LFS_ASSERT(lfs->cfg->lookahead > 0); LFS_ASSERT(lfs->cfg->lookahead_size > 0);
if (lfs->cfg->lookahead_buffer) { if (lfs->cfg->lookahead_buffer) {
lfs->free.buffer = lfs->cfg->lookahead_buffer; lfs->free.buffer = lfs->cfg->lookahead_buffer;
} else { } else {
lfs->free.buffer = lfs_malloc(lfs->cfg->lookahead/8); lfs->free.buffer = lfs_malloc(lfs->cfg->lookahead_size);
if (!lfs->free.buffer) { if (!lfs->free.buffer) {
err = LFS_ERR_NOMEM; err = LFS_ERR_NOMEM;
goto cleanup; goto cleanup;
@@ -3112,9 +3112,10 @@ int lfs_format(lfs_t *lfs, const struct lfs_config *cfg) {
} }
// create free lookahead // create free lookahead
memset(lfs->free.buffer, 0, lfs->cfg->lookahead/8); memset(lfs->free.buffer, 0, lfs->cfg->lookahead_size);
lfs->free.off = 0; lfs->free.off = 0;
lfs->free.size = lfs_min(lfs->cfg->lookahead, lfs->cfg->block_count); lfs->free.size = lfs_min(8*lfs->cfg->lookahead_size,
lfs->cfg->block_count);
lfs->free.i = 0; lfs->free.i = 0;
lfs_alloc_ack(lfs); lfs_alloc_ack(lfs);

40
lfs.h
View File

@@ -177,39 +177,41 @@ struct lfs_config {
lfs_size_t prog_size; lfs_size_t prog_size;
// Size of an erasable block. This does not impact ram consumption and // Size of an erasable block. This does not impact ram consumption and
// may be larger than the physical erase size. However, this should be // may be larger than the physical erase size. However, non-inlined files
// kept small as each file currently takes up an entire block. // take up at minimum one block. Must be a multiple of the read
// Must be a multiple of the read, program, and cache sizes. // and program sizes.
lfs_size_t block_size; lfs_size_t block_size;
// Number of erasable blocks on the device. // Number of erasable blocks on the device.
lfs_size_t block_count; lfs_size_t block_count;
// Number of erase cycles before we should move data to another block. // Number of erase cycles before we should move data to another block.
// May be zero to never move data, in which case no block-level // May be zero, in which case no block-level wear-leveling is performed.
// wear-leveling is performed.
uint32_t block_cycles; uint32_t block_cycles;
// Size of block caches. Each cache buffers a portion of a block in RAM. // Size of block caches. Each cache buffers a portion of a block in RAM.
// This determines the size of the read cache, the program cache, and a // The littlefs needs a read cache, a program cache, and one additional
// cache per file. Larger caches can improve performance by storing more // cache per file. Larger caches can improve performance by storing more
// data. Must be a multiple of the read and program sizes. // data and reducing the number of disk accesses. Must be a multiple of
// the read and program sizes, and a factor of the block size.
lfs_size_t cache_size; lfs_size_t cache_size;
// Number of blocks to lookahead during block allocation. A larger // Size of the lookahead buffer in bytes. A larger lookahead buffer
// lookahead reduces the number of passes required to allocate a block. // increases the number of blocks found during an allocation pass. The
// The lookahead buffer requires only 1 bit per block so it can be quite // lookahead buffer is stored as a compact bitmap, so each byte of RAM
// large with little ram impact. Should be a multiple of 32. // can track 8 blocks. Must be a multiple of 4.
lfs_size_t lookahead; lfs_size_t lookahead_size;
// Optional, statically allocated read buffer. Must be read sized. // Optional statically allocated read buffer. Must be cache_size.
// By default lfs_malloc is used to allocate this buffer.
void *read_buffer; void *read_buffer;
// Optional, statically allocated program buffer. Must be program sized. // Optional statically allocated program buffer. Must be cache_size.
// By default lfs_malloc is used to allocate this buffer.
void *prog_buffer; void *prog_buffer;
// Optional, statically allocated lookahead buffer. Must be 1 bit per // Optional statically allocated program buffer. Must be lookahead_size.
// lookahead block. // By default lfs_malloc is used to allocate this buffer.
void *lookahead_buffer; void *lookahead_buffer;
// Optional upper limit on length of file names in bytes. No downside for // Optional upper limit on length of file names in bytes. No downside for
@@ -266,11 +268,11 @@ struct lfs_attr {
// Optional configuration provided during lfs_file_opencfg // Optional configuration provided during lfs_file_opencfg
struct lfs_file_config { struct lfs_file_config {
// Optional, statically allocated buffer for files. Must be program sized. // Optional statically allocated file buffer. Must be cache_size.
// If NULL, malloc will be used by default. // By default lfs_malloc is used to allocate this buffer.
void *buffer; void *buffer;
// Optional, linked list of custom attributes related to the file. If the // Optional linked list of custom attributes related to the file. If the
// file is opened with read access, the attributes will be read from // file is opened with read access, the attributes will be read from
// during the open call. If the file is opened with write access, the // during the open call. If the file is opened with write access, the
// attributes will be written to disk every file sync or close. This // attributes will be written to disk every file sync or close. This

View File

@@ -85,8 +85,8 @@ uintmax_t test;
#define LFS_CACHE_SIZE 64 #define LFS_CACHE_SIZE 64
#endif #endif
#ifndef LFS_LOOKAHEAD #ifndef LFS_LOOKAHEAD_SIZE
#define LFS_LOOKAHEAD 128 #define LFS_LOOKAHEAD_SIZE 16
#endif #endif
const struct lfs_config cfg = {{ const struct lfs_config cfg = {{
@@ -96,13 +96,13 @@ const struct lfs_config cfg = {{
.erase = &lfs_emubd_erase, .erase = &lfs_emubd_erase,
.sync = &lfs_emubd_sync, .sync = &lfs_emubd_sync,
.read_size = LFS_READ_SIZE, .read_size = LFS_READ_SIZE,
.prog_size = LFS_PROG_SIZE, .prog_size = LFS_PROG_SIZE,
.block_size = LFS_BLOCK_SIZE, .block_size = LFS_BLOCK_SIZE,
.block_count = LFS_BLOCK_COUNT, .block_count = LFS_BLOCK_COUNT,
.block_cycles = LFS_BLOCK_CYCLES, .block_cycles = LFS_BLOCK_CYCLES,
.cache_size = LFS_CACHE_SIZE, .cache_size = LFS_CACHE_SIZE,
.lookahead = LFS_LOOKAHEAD, .lookahead_size = LFS_LOOKAHEAD_SIZE,
}}; }};