WIP Added support for cache_size as alternative to read_size and

prog_size
This commit is contained in:
Christopher Haster
2018-08-04 14:48:27 -05:00
parent e7c4465bf5
commit a98affc951
5 changed files with 108 additions and 108 deletions

View File

@@ -18,8 +18,8 @@ script:
- make test QUIET=1 - make test QUIET=1
# run tests with a few different configurations # run tests with a few different configurations
- make test QUIET=1 CFLAGS+="-DLFS_READ_SIZE=1 -DLFS_PROG_SIZE=1" - make test QUIET=1 CFLAGS+="-DLFS_READ_SIZE=1 -DLFS_CACHE_SIZE=4"
- make test QUIET=1 CFLAGS+="-DLFS_READ_SIZE=512 -DLFS_PROG_SIZE=512" - make test QUIET=1 CFLAGS+="-DLFS_READ_SIZE=512 -DLFS_CACHE_SIZE=512"
- make test QUIET=1 CFLAGS+="-DLFS_BLOCK_COUNT=1023 -DLFS_LOOKAHEAD=2048" - make test QUIET=1 CFLAGS+="-DLFS_BLOCK_COUNT=1023 -DLFS_LOOKAHEAD=2048"
- make clean test QUIET=1 CFLAGS+="-DLFS_INLINE_MAX=0" - make clean test QUIET=1 CFLAGS+="-DLFS_INLINE_MAX=0"

179
lfs.c
View File

@@ -20,18 +20,19 @@
/// Caching block device operations /// /// Caching block device operations ///
static int lfs_cache_read(lfs_t *lfs, lfs_cache_t *rcache, static int lfs_cache_read(lfs_t *lfs,
const lfs_cache_t *pcache, lfs_block_t block, const lfs_cache_t *pcache, lfs_cache_t *rcache, bool store,
lfs_off_t off, void *buffer, lfs_size_t size) { lfs_block_t block, lfs_off_t off,
void *buffer, lfs_size_t size) {
uint8_t *data = buffer; uint8_t *data = buffer;
LFS_ASSERT(block != 0xffffffff); LFS_ASSERT(block != 0xffffffff);
while (size > 0) { while (size > 0) {
if (pcache && block == pcache->block && off >= pcache->off && if (pcache && block == pcache->block &&
off < pcache->off + lfs->cfg->prog_size) { off >= pcache->off &&
off < pcache->off + pcache->size) {
// is already in pcache? // is already in pcache?
lfs_size_t diff = lfs_min(size, lfs_size_t diff = lfs_min(size, pcache->size - (off-pcache->off));
lfs->cfg->prog_size - (off-pcache->off));
memcpy(data, &pcache->buffer[off-pcache->off], diff); memcpy(data, &pcache->buffer[off-pcache->off], diff);
data += diff; data += diff;
@@ -40,11 +41,14 @@ static int lfs_cache_read(lfs_t *lfs, lfs_cache_t *rcache,
continue; continue;
} }
if (block == rcache->block && off >= rcache->off && if (block == rcache->block &&
off < rcache->off + lfs->cfg->read_size) { off >= rcache->off &&
off < rcache->off + rcache->size) {
// is already in rcache? // is already in rcache?
lfs_size_t diff = lfs_min(size, lfs_size_t diff = lfs_min(size, rcache->size - (off-rcache->off));
lfs->cfg->read_size - (off-rcache->off)); if (pcache && block == pcache->block) {
diff = lfs_min(diff, pcache->off - off);
}
memcpy(data, &rcache->buffer[off-rcache->off], diff); memcpy(data, &rcache->buffer[off-rcache->off], diff);
data += diff; data += diff;
@@ -53,7 +57,8 @@ static int lfs_cache_read(lfs_t *lfs, lfs_cache_t *rcache,
continue; continue;
} }
if (off % lfs->cfg->read_size == 0 && size >= lfs->cfg->read_size) { if (!store && off % lfs->cfg->read_size == 0 &&
size >= lfs->cfg->read_size) {
// bypass cache? // bypass cache?
lfs_size_t diff = size - (size % lfs->cfg->read_size); lfs_size_t diff = size - (size % lfs->cfg->read_size);
int err = lfs->cfg->read(lfs->cfg, block, off, data, diff); int err = lfs->cfg->read(lfs->cfg, block, off, data, diff);
@@ -69,10 +74,12 @@ static int lfs_cache_read(lfs_t *lfs, lfs_cache_t *rcache,
// load to cache, first condition can no longer fail // load to cache, first condition can no longer fail
LFS_ASSERT(block < lfs->cfg->block_count); LFS_ASSERT(block < lfs->cfg->block_count);
lfs_size_t size = store ? lfs->cfg->cache_size : lfs->cfg->prog_size;
rcache->block = block; rcache->block = block;
rcache->off = off - (off % lfs->cfg->read_size); rcache->off = lfs_aligndown(off, size);
rcache->size = size;
int err = lfs->cfg->read(lfs->cfg, rcache->block, int err = lfs->cfg->read(lfs->cfg, rcache->block,
rcache->off, rcache->buffer, lfs->cfg->read_size); rcache->off, rcache->buffer, size);
if (err) { if (err) {
return err; return err;
} }
@@ -81,14 +88,15 @@ static int lfs_cache_read(lfs_t *lfs, lfs_cache_t *rcache,
return 0; return 0;
} }
static int lfs_cache_cmp(lfs_t *lfs, lfs_cache_t *rcache, static int lfs_cache_cmp(lfs_t *lfs,
const lfs_cache_t *pcache, lfs_block_t block, const lfs_cache_t *pcache, lfs_cache_t *rcache,
lfs_off_t off, const void *buffer, lfs_size_t size) { lfs_block_t block, lfs_off_t off,
const void *buffer, lfs_size_t size) {
const uint8_t *data = buffer; const uint8_t *data = buffer;
for (lfs_off_t i = 0; i < size; i++) { for (lfs_off_t i = 0; i < size; i++) {
uint8_t c; uint8_t c;
int err = lfs_cache_read(lfs, rcache, pcache, int err = lfs_cache_read(lfs, pcache, rcache, true,
block, off+i, &c, 1); block, off+i, &c, 1);
if (err) { if (err) {
return err; return err;
@@ -102,12 +110,12 @@ static int lfs_cache_cmp(lfs_t *lfs, lfs_cache_t *rcache,
return true; return true;
} }
static int lfs_cache_crc(lfs_t *lfs, lfs_cache_t *rcache, static int lfs_cache_crc(lfs_t *lfs,
const lfs_cache_t *pcache, lfs_block_t block, const lfs_cache_t *pcache, lfs_cache_t *rcache,
lfs_off_t off, lfs_size_t size, uint32_t *crc) { lfs_block_t block, lfs_off_t off, lfs_size_t size, uint32_t *crc) {
for (lfs_off_t i = 0; i < size; i++) { for (lfs_off_t i = 0; i < size; i++) {
uint8_t c; uint8_t c;
int err = lfs_cache_read(lfs, rcache, pcache, int err = lfs_cache_read(lfs, pcache, rcache, true,
block, off+i, &c, 1); block, off+i, &c, 1);
if (err) { if (err) {
return err; return err;
@@ -120,18 +128,21 @@ static int lfs_cache_crc(lfs_t *lfs, lfs_cache_t *rcache,
} }
static int lfs_cache_flush(lfs_t *lfs, static int lfs_cache_flush(lfs_t *lfs,
lfs_cache_t *pcache, lfs_cache_t *rcache) { lfs_cache_t *pcache, lfs_cache_t *rcache, bool validate) {
if (pcache->block != 0xffffffff) { if (pcache->block != 0xffffffff) {
LFS_ASSERT(pcache->block < lfs->cfg->block_count); LFS_ASSERT(pcache->block < lfs->cfg->block_count);
lfs_size_t diff = lfs_alignup(pcache->size, lfs->cfg->prog_size);
int err = lfs->cfg->prog(lfs->cfg, pcache->block, int err = lfs->cfg->prog(lfs->cfg, pcache->block,
pcache->off, pcache->buffer, lfs->cfg->prog_size); pcache->off, pcache->buffer, diff);
if (err) { if (err) {
return err; return err;
} }
if (rcache) { if (validate) {
int res = lfs_cache_cmp(lfs, rcache, NULL, pcache->block, // check data on disk
pcache->off, pcache->buffer, lfs->cfg->prog_size); rcache->block = 0xffffffff;
int res = lfs_cache_cmp(lfs, NULL, rcache, pcache->block,
pcache->off, pcache->buffer, diff);
if (res < 0) { if (res < 0) {
return res; return res;
} }
@@ -147,28 +158,31 @@ static int lfs_cache_flush(lfs_t *lfs,
return 0; return 0;
} }
static int lfs_cache_prog(lfs_t *lfs, lfs_cache_t *pcache, static int lfs_cache_prog(lfs_t *lfs,
lfs_cache_t *rcache, lfs_block_t block, lfs_cache_t *pcache, lfs_cache_t *rcache, bool validate,
lfs_off_t off, const void *buffer, lfs_size_t size) { lfs_block_t block, lfs_off_t off,
const void *buffer, lfs_size_t size) {
const uint8_t *data = buffer; const uint8_t *data = buffer;
LFS_ASSERT(block != 0xffffffff); LFS_ASSERT(block != 0xffffffff);
LFS_ASSERT(off + size <= lfs->cfg->block_size); LFS_ASSERT(off + size <= lfs->cfg->block_size);
while (size > 0) { while (size > 0) {
if (block == pcache->block && off >= pcache->off && if (block == pcache->block &&
off < pcache->off + lfs->cfg->prog_size) { off >= pcache->off &&
// is already in pcache? off < pcache->off + lfs->cfg->cache_size) {
// already fits in pcache?
lfs_size_t diff = lfs_min(size, lfs_size_t diff = lfs_min(size,
lfs->cfg->prog_size - (off-pcache->off)); lfs->cfg->cache_size - (off-pcache->off));
memcpy(&pcache->buffer[off-pcache->off], data, diff); memcpy(&pcache->buffer[off-pcache->off], data, diff);
data += diff; data += diff;
off += diff; off += diff;
size -= diff; size -= diff;
if (off % lfs->cfg->prog_size == 0) { pcache->size = off - pcache->off;
if (pcache->size == lfs->cfg->cache_size) {
// eagerly flush out pcache if we fill up // eagerly flush out pcache if we fill up
int err = lfs_cache_flush(lfs, pcache, rcache); int err = lfs_cache_flush(lfs, pcache, rcache, validate);
if (err) { if (err) {
return err; return err;
} }
@@ -181,37 +195,10 @@ static int lfs_cache_prog(lfs_t *lfs, lfs_cache_t *pcache,
// entire block or manually flushing the pcache // entire block or manually flushing the pcache
LFS_ASSERT(pcache->block == 0xffffffff); LFS_ASSERT(pcache->block == 0xffffffff);
if (off % lfs->cfg->prog_size == 0 &&
size >= lfs->cfg->prog_size) {
// bypass pcache?
LFS_ASSERT(block < lfs->cfg->block_count);
lfs_size_t diff = size - (size % lfs->cfg->prog_size);
int err = lfs->cfg->prog(lfs->cfg, block, off, data, diff);
if (err) {
return err;
}
if (rcache) {
int res = lfs_cache_cmp(lfs, rcache, NULL,
block, off, data, diff);
if (res < 0) {
return res;
}
if (!res) {
return LFS_ERR_CORRUPT;
}
}
data += diff;
off += diff;
size -= diff;
continue;
}
// prepare pcache, first condition can no longer fail // prepare pcache, first condition can no longer fail
pcache->block = block; pcache->block = block;
pcache->off = off - (off % lfs->cfg->prog_size); pcache->off = lfs_aligndown(off, lfs->cfg->prog_size);
pcache->size = 0;
} }
return 0; return 0;
@@ -221,24 +208,24 @@ static int lfs_cache_prog(lfs_t *lfs, lfs_cache_t *pcache,
/// General lfs block device operations /// /// General lfs block device operations ///
static int lfs_bd_read(lfs_t *lfs, lfs_block_t block, static int lfs_bd_read(lfs_t *lfs, lfs_block_t block,
lfs_off_t off, void *buffer, lfs_size_t size) { lfs_off_t off, void *buffer, lfs_size_t size) {
return lfs_cache_read(lfs, &lfs->rcache, &lfs->pcache, return lfs_cache_read(lfs, &lfs->pcache, &lfs->rcache, true,
block, off, buffer, size); block, off, buffer, size);
} }
static int lfs_bd_prog(lfs_t *lfs, lfs_block_t block, static int lfs_bd_prog(lfs_t *lfs, 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) {
return lfs_cache_prog(lfs, &lfs->pcache, NULL, return lfs_cache_prog(lfs, &lfs->pcache, &lfs->rcache, false,
block, off, buffer, size); block, off, buffer, size);
} }
static int lfs_bd_cmp(lfs_t *lfs, lfs_block_t block, static int lfs_bd_cmp(lfs_t *lfs, 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) {
return lfs_cache_cmp(lfs, &lfs->rcache, NULL, block, off, buffer, size); return lfs_cache_cmp(lfs, NULL, &lfs->rcache, block, off, buffer, size);
} }
static int lfs_bd_crc(lfs_t *lfs, lfs_block_t block, static int lfs_bd_crc(lfs_t *lfs, lfs_block_t block,
lfs_off_t off, lfs_size_t size, uint32_t *crc) { lfs_off_t off, lfs_size_t size, uint32_t *crc) {
return lfs_cache_crc(lfs, &lfs->rcache, NULL, block, off, size, crc); return lfs_cache_crc(lfs, NULL, &lfs->rcache, block, off, size, crc);
} }
static int lfs_bd_erase(lfs_t *lfs, lfs_block_t block) { static int lfs_bd_erase(lfs_t *lfs, lfs_block_t block) {
@@ -249,7 +236,7 @@ static int lfs_bd_erase(lfs_t *lfs, lfs_block_t block) {
static int lfs_bd_sync(lfs_t *lfs) { static int lfs_bd_sync(lfs_t *lfs) {
lfs->rcache.block = 0xffffffff; lfs->rcache.block = 0xffffffff;
int err = lfs_cache_flush(lfs, &lfs->pcache, NULL); int err = lfs_cache_flush(lfs, &lfs->pcache, &lfs->rcache, false);
if (err) { if (err) {
return err; return err;
} }
@@ -1658,7 +1645,8 @@ static int lfs_ctzfind(lfs_t *lfs,
lfs_npw2(current-target+1) - 1, lfs_npw2(current-target+1) - 1,
lfs_ctz(current)); lfs_ctz(current));
int err = lfs_cache_read(lfs, rcache, pcache, head, 4*skip, &head, 4); int err = lfs_cache_read(lfs, pcache, rcache, false,
head, 4*skip, &head, 4);
head = lfs_fromle32(head); head = lfs_fromle32(head);
if (err) { if (err) {
return err; return err;
@@ -1709,13 +1697,13 @@ static int lfs_ctzextend(lfs_t *lfs,
if (size != lfs->cfg->block_size) { if (size != lfs->cfg->block_size) {
for (lfs_off_t i = 0; i < size; i++) { for (lfs_off_t i = 0; i < size; i++) {
uint8_t data; uint8_t data;
err = lfs_cache_read(lfs, rcache, NULL, err = lfs_cache_read(lfs, NULL, rcache, true,
head, i, &data, 1); head, i, &data, 1);
if (err) { if (err) {
return err; return err;
} }
err = lfs_cache_prog(lfs, pcache, rcache, err = lfs_cache_prog(lfs, pcache, rcache, true,
nblock, i, &data, 1); nblock, i, &data, 1);
if (err) { if (err) {
if (err == LFS_ERR_CORRUPT) { if (err == LFS_ERR_CORRUPT) {
@@ -1736,7 +1724,7 @@ static int lfs_ctzextend(lfs_t *lfs,
for (lfs_off_t i = 0; i < skips; i++) { for (lfs_off_t i = 0; i < skips; i++) {
head = lfs_tole32(head); head = lfs_tole32(head);
err = lfs_cache_prog(lfs, pcache, rcache, err = lfs_cache_prog(lfs, pcache, rcache, true,
nblock, 4*i, &head, 4); nblock, 4*i, &head, 4);
head = lfs_fromle32(head); head = lfs_fromle32(head);
if (err) { if (err) {
@@ -1747,7 +1735,7 @@ static int lfs_ctzextend(lfs_t *lfs,
} }
if (i != skips-1) { if (i != skips-1) {
err = lfs_cache_read(lfs, rcache, NULL, err = lfs_cache_read(lfs, NULL, rcache, false,
head, 4*i, &head, 4); head, 4*i, &head, 4);
head = lfs_fromle32(head); head = lfs_fromle32(head);
if (err) { if (err) {
@@ -1793,7 +1781,8 @@ static int lfs_ctztraverse(lfs_t *lfs,
lfs_block_t heads[2]; lfs_block_t heads[2];
int count = 2 - (index & 1); int count = 2 - (index & 1);
err = lfs_cache_read(lfs, rcache, pcache, head, 0, &heads, count*4); err = lfs_cache_read(lfs, pcache, rcache, false,
head, 0, &heads, count*4);
heads[0] = lfs_fromle32(heads[0]); heads[0] = lfs_fromle32(heads[0]);
heads[1] = lfs_fromle32(heads[1]); heads[1] = lfs_fromle32(heads[1]);
if (err) { if (err) {
@@ -1916,15 +1905,8 @@ int lfs_file_opencfg(lfs_t *lfs, lfs_file_t *file,
file->cache.block = 0xffffffff; file->cache.block = 0xffffffff;
if (file->cfg->buffer) { if (file->cfg->buffer) {
file->cache.buffer = file->cfg->buffer; file->cache.buffer = file->cfg->buffer;
} else if ((file->flags & 3) == LFS_O_RDONLY) {
// TODO cache_size
file->cache.buffer = lfs_malloc(lfs->cfg->read_size);
if (!file->cache.buffer) {
err = LFS_ERR_NOMEM;
goto cleanup;
}
} else { } else {
file->cache.buffer = lfs_malloc(lfs->cfg->prog_size); file->cache.buffer = lfs_malloc(lfs->cfg->cache_size);
if (!file->cache.buffer) { if (!file->cache.buffer) {
err = LFS_ERR_NOMEM; err = LFS_ERR_NOMEM;
goto cleanup; goto cleanup;
@@ -1938,6 +1920,7 @@ int lfs_file_opencfg(lfs_t *lfs, lfs_file_t *file,
file->flags |= LFS_F_INLINE; file->flags |= LFS_F_INLINE;
file->cache.block = file->ctz.head; file->cache.block = file->ctz.head;
file->cache.off = 0; file->cache.off = 0;
file->cache.size = lfs->cfg->cache_size;
// don't always read (may be new/trunc file) // don't always read (may be new/trunc file)
if (file->ctz.size > 0) { if (file->ctz.size > 0) {
@@ -2005,13 +1988,13 @@ static int lfs_file_relocate(lfs_t *lfs, lfs_file_t *file) {
// either read from dirty cache or disk // either read from dirty cache or disk
for (lfs_off_t i = 0; i < file->off; i++) { for (lfs_off_t i = 0; i < file->off; i++) {
uint8_t data; uint8_t data;
err = lfs_cache_read(lfs, &lfs->rcache, &file->cache, err = lfs_cache_read(lfs, &file->cache, &lfs->rcache, true,
file->block, i, &data, 1); file->block, i, &data, 1);
if (err) { if (err) {
return err; return err;
} }
err = lfs_cache_prog(lfs, &lfs->pcache, &lfs->rcache, err = lfs_cache_prog(lfs, &lfs->pcache, &lfs->rcache, true,
nblock, i, &data, 1); nblock, i, &data, 1);
if (err) { if (err) {
if (err == LFS_ERR_CORRUPT) { if (err == LFS_ERR_CORRUPT) {
@@ -2022,9 +2005,10 @@ static int lfs_file_relocate(lfs_t *lfs, lfs_file_t *file) {
} }
// copy over new state of file // copy over new state of file
memcpy(file->cache.buffer, lfs->pcache.buffer, lfs->cfg->prog_size); memcpy(file->cache.buffer, lfs->pcache.buffer, lfs->cfg->cache_size);
file->cache.block = lfs->pcache.block; file->cache.block = lfs->pcache.block;
file->cache.off = lfs->pcache.off; file->cache.off = lfs->pcache.off;
file->cache.size = lfs->pcache.size;
lfs->pcache.block = 0xffffffff; lfs->pcache.block = 0xffffffff;
file->block = nblock; file->block = nblock;
@@ -2077,7 +2061,8 @@ static int lfs_file_flush(lfs_t *lfs, lfs_file_t *file) {
// write out what we have // write out what we have
while (true) { while (true) {
int err = lfs_cache_flush(lfs, &file->cache, &lfs->rcache); int err = lfs_cache_flush(lfs,
&file->cache, &lfs->rcache, true);
if (err) { if (err) {
if (err == LFS_ERR_CORRUPT) { if (err == LFS_ERR_CORRUPT) {
goto relocate; goto relocate;
@@ -2217,7 +2202,7 @@ lfs_ssize_t lfs_file_read(lfs_t *lfs, lfs_file_t *file,
// read as much as we can in current block // read as much as we can in current block
lfs_size_t diff = lfs_min(nsize, lfs->cfg->block_size - file->off); lfs_size_t diff = lfs_min(nsize, lfs->cfg->block_size - file->off);
int err = lfs_cache_read(lfs, &file->cache, NULL, int err = lfs_cache_read(lfs, NULL, &file->cache, true,
file->block, file->off, data, diff); file->block, file->off, data, diff);
if (err) { if (err) {
return err; return err;
@@ -2322,7 +2307,7 @@ lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file,
// program as much as we can in current block // program as much as we can in current block
lfs_size_t diff = lfs_min(nsize, lfs->cfg->block_size - file->off); lfs_size_t diff = lfs_min(nsize, lfs->cfg->block_size - file->off);
while (true) { while (true) {
int err = lfs_cache_prog(lfs, &file->cache, &lfs->rcache, int err = lfs_cache_prog(lfs, &file->cache, &lfs->rcache, true,
file->block, file->off, data, diff); file->block, file->off, data, diff);
if (err) { if (err) {
if (err == LFS_ERR_CORRUPT) { if (err == LFS_ERR_CORRUPT) {
@@ -2723,7 +2708,7 @@ static int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) {
if (lfs->cfg->read_buffer) { if (lfs->cfg->read_buffer) {
lfs->rcache.buffer = lfs->cfg->read_buffer; lfs->rcache.buffer = lfs->cfg->read_buffer;
} else { } else {
lfs->rcache.buffer = lfs_malloc(lfs->cfg->read_size); lfs->rcache.buffer = lfs_malloc(lfs->cfg->cache_size);
if (!lfs->rcache.buffer) { if (!lfs->rcache.buffer) {
return LFS_ERR_NOMEM; return LFS_ERR_NOMEM;
} }
@@ -2734,7 +2719,7 @@ static int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) {
if (lfs->cfg->prog_buffer) { if (lfs->cfg->prog_buffer) {
lfs->pcache.buffer = lfs->cfg->prog_buffer; lfs->pcache.buffer = lfs->cfg->prog_buffer;
} else { } else {
lfs->pcache.buffer = lfs_malloc(lfs->cfg->prog_size); lfs->pcache.buffer = lfs_malloc(lfs->cfg->cache_size);
if (!lfs->pcache.buffer) { if (!lfs->pcache.buffer) {
return LFS_ERR_NOMEM; return LFS_ERR_NOMEM;
} }
@@ -2752,9 +2737,11 @@ static int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) {
} }
} }
// check that program and read sizes are multiples of the block size // check that block size is a multiple of cache size is a multiple
LFS_ASSERT(lfs->cfg->prog_size % lfs->cfg->read_size == 0); // of prog and read sizes
LFS_ASSERT(lfs->cfg->block_size % lfs->cfg->prog_size == 0); LFS_ASSERT(lfs->cfg->cache_size % lfs->cfg->read_size == 0);
LFS_ASSERT(lfs->cfg->cache_size % lfs->cfg->prog_size == 0);
LFS_ASSERT(lfs->cfg->block_size % lfs->cfg->cache_size == 0);
// check that the block size is large enough to fit ctz pointers // check that the block size is large enough to fit ctz pointers
LFS_ASSERT(4*lfs_npw2(0xffffffff / (lfs->cfg->block_size-2*4)) LFS_ASSERT(4*lfs_npw2(0xffffffff / (lfs->cfg->block_size-2*4))
@@ -2762,7 +2749,7 @@ static int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) {
// check that the size limits are sane // check that the size limits are sane
LFS_ASSERT(lfs->cfg->inline_size <= LFS_INLINE_MAX); LFS_ASSERT(lfs->cfg->inline_size <= LFS_INLINE_MAX);
LFS_ASSERT(lfs->cfg->inline_size <= lfs->cfg->read_size); LFS_ASSERT(lfs->cfg->inline_size <= lfs->cfg->read_size); // TODO
lfs->inline_size = lfs->cfg->inline_size; lfs->inline_size = lfs->cfg->inline_size;
if (!lfs->inline_size) { if (!lfs->inline_size) {
lfs->inline_size = lfs_min(LFS_INLINE_MAX, lfs->cfg->read_size); lfs->inline_size = lfs_min(LFS_INLINE_MAX, lfs->cfg->read_size);

20
lfs.h
View File

@@ -177,21 +177,24 @@ struct lfs_config {
// are propogated to the user. // are propogated to the user.
int (*sync)(const struct lfs_config *c); int (*sync)(const struct lfs_config *c);
// Minimum size of a block read. This determines the size of read buffers. // Minimum size of a block read. All read operations will be a
// This may be larger than the physical read size to improve performance // multiple of this value.
// by caching more of the block device.
lfs_size_t read_size; lfs_size_t read_size;
// Minimum size of a block program. This determines the size of program // Minimum size of a block program. All program operations will be a
// buffers. This may be larger than the physical program size to improve // multiple of this value.
// performance by caching more of the block device.
// Must be a multiple of the read size.
lfs_size_t prog_size; lfs_size_t prog_size;
// 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
// cache per file. Larger caches can improve performance by storing more
// data. Must be a multiple of the read and program sizes.
lfs_size_t cache_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, this should be
// kept small as each file currently takes up an entire block. // kept small as each file currently takes up an entire block.
// Must be a multiple of the program size. // Must be a multiple of the read, program, and cache 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.
@@ -283,6 +286,7 @@ typedef struct lfs_mattr {
typedef struct lfs_cache { typedef struct lfs_cache {
lfs_block_t block; lfs_block_t block;
lfs_off_t off; lfs_off_t off;
lfs_size_t size;
uint8_t *buffer; uint8_t *buffer;
} lfs_cache_t; } lfs_cache_t;

View File

@@ -183,8 +183,12 @@ static inline uint16_t lfs_tole16(uint16_t a) {
} }
// Align to nearest multiple of a size // Align to nearest multiple of a size
static inline uint32_t lfs_aligndown(uint32_t a, uint32_t alignment) {
return a - (a % alignment);
}
static inline uint32_t lfs_alignup(uint32_t a, uint32_t alignment) { static inline uint32_t lfs_alignup(uint32_t a, uint32_t alignment) {
return (a + alignment-1) - ((a + alignment-1) % alignment); return lfs_aligndown(a + alignment-1, alignment);
} }
// Calculate CRC-32 with polynomial = 0x04c11db7 // Calculate CRC-32 with polynomial = 0x04c11db7

View File

@@ -66,7 +66,11 @@ uintmax_t test;
#endif #endif
#ifndef LFS_PROG_SIZE #ifndef LFS_PROG_SIZE
#define LFS_PROG_SIZE 16 #define LFS_PROG_SIZE LFS_READ_SIZE
#endif
#ifndef LFS_CACHE_SIZE
#define LFS_CACHE_SIZE 64
#endif #endif
#ifndef LFS_BLOCK_SIZE #ifndef LFS_BLOCK_SIZE
@@ -92,6 +96,7 @@ const struct lfs_config cfg = {{
.read_size = LFS_READ_SIZE, .read_size = LFS_READ_SIZE,
.prog_size = LFS_PROG_SIZE, .prog_size = LFS_PROG_SIZE,
.cache_size = LFS_CACHE_SIZE,
.block_size = LFS_BLOCK_SIZE, .block_size = LFS_BLOCK_SIZE,
.block_count = LFS_BLOCK_COUNT, .block_count = LFS_BLOCK_COUNT,
.lookahead = LFS_LOOKAHEAD, .lookahead = LFS_LOOKAHEAD,